初学者:《C++ STL容器入门:手把手教你使用常用容器》

《C++ STL容器入门:手把手教你使用常用容器》

适合人群:刚接触C++不久,还没系统用过STL容器,或者用过但总觉得混乱的初学者。

我们今天按「最常用 → 次常用 → 特殊场景」的顺序,把最核心的6个容器讲清楚:

容器类型底层实现是否有序是否允许重复随机访问最典型用途初学者记住的关键词
vector动态数组有序允许O(1)「大多数情况下的默认选择」连续、可扩容
string字符动态数组有序允许O(1)字符串vector 的亲兄弟
deque分段连续数组有序允许O(1)头尾频繁插入/删除两端队列
list双向链表有序允许O(n)中间频繁插入/删除不连续、指针跳转
set / multiset红黑树有序set不允许
multiset允许
自动排序 + 去重有序集合
unordered_set哈希表无序不允许快速判断“是否存在”哈希去重、O(1)查找

一、vector(99%新手最该先掌握的容器)

#include <vector>
#include <iostream>
using namespace std;

int main() {
    // 1. 几种常见创建方式
    vector<int> v1;                    // 空vector
    vector<int> v2(10);                // 10个0
    vector<int> v3(10, 7);             // 10个7
    vector<int> v4 = {1, 2, 3, 4, 5};  // 初始化列表(最常用!)

    // 2. 常用操作
    v4.push_back(6);          // 尾部添加     O(1) 均摊
    v4.pop_back();            // 尾部删除     O(1)
    cout << v4.size() << endl;       // 当前元素个数
    cout << v4.capacity() << endl;   // 已分配空间(≥size)

    // 3. 遍历(四种写法,推荐前两种)
    // 写法1:范围for(最简洁,C++11+)
    for(int x : v4) {
        cout << x << " ";
    }
    cout << endl;

    // 写法2:现代for + 下标(最常用)
    for(size_t i = 0; i < v4.size(); ++i) {
        cout << v4[i] << " ";
    }
    cout << endl;

    // 写法3:迭代器(了解即可)
    for(auto it = v4.begin(); it != v4.end(); ++it) {
        cout << *it << " ";
    }

    // 4. 访问(越界是未定义行为!)
    cout << v4.front() << endl;   // 第一个元素
    cout << v4.back() << endl;    // 最后一个元素
    cout << v4[2] << endl;        // 下标访问(不检查边界)
    cout << v4.at(2) << endl;     // 边界检查版(越界抛异常)

    // 5. 提前分配空间(非常重要!性能差距可达数倍)
    vector<int> large;
    large.reserve(1000000);     // 提前申请100万空间,避免多次扩容

    return 0;
}

vector使用铁律(背下来)

  1. 不知道用什么容器的时候 → 先用 vector
  2. 需要频繁在中间插入/删除 → 才考虑 list / deque
  3. 明确知道最终大小 → 构造时直接给大小 或 reserve
  4. 尽量用 v[i] 而不是 at(i)(性能更好,但自己保证不越界)

二、string(其实就是 vector 的特化版)

string s = "hello";

// 常用操作(几乎和 vector 一样)
s += " world";          // 拼接
s.push_back('!');       
s.pop_back();
cout << s.size() << " " << s.length() << endl;  // 两者等价
cout << s.empty() << endl;

// 查找
size_t pos = s.find("world");     // 返回下标,没找到返回 string::npos
if (pos != string::npos) {
    cout << "找到了,位置:" << pos << endl;
}

// 替换、插入、删除
s.replace(0, 5, "Hi");          // 把前5个字符替换成 "Hi"
s.insert(2, "~~~");             // 在下标2处插入
s.erase(2, 3);                  // 从下标2开始删3个字符

// 子串
string sub = s.substr(0, 5);    // 前5个字符

三、deque(双端队列)

#include <deque>

deque<int> dq;
dq.push_back(10);     // 尾插
dq.push_front(5);     // 头插
dq.pop_back();        // 尾删
dq.pop_front();       // 头删

// 支持随机访问(但比 vector 稍慢)
cout << dq[0] << " " << dq.at(1) << endl;

什么时候用 deque 而不是 vector?

  • 需要频繁在头部插入/删除
  • 想用队列,但又偶尔需要随机访问

四、list(双向链表)

#include <list>

list<int> lst = {1, 2, 3, 4, 5};
lst.push_front(0);
lst.push_back(6);

// 中间插入(已知位置时效率很高)
auto it = lst.begin();
++it; ++it;           // 指向第三个元素(值为3)
lst.insert(it, 99);   // 在3前面插入99

// 删除(已知迭代器时效率很高)
lst.erase(it);        // 删除刚才的迭代器位置

list最大特点
任意位置插入/删除都是 O(1)(只要你已经拿到迭代器),但不支持随机访问([] 运算符)。

五、set / multiset(自动排序 + 去重)

#include <set>

set<int> s;
s.insert(3);
s.insert(1);
s.insert(3);          // 重复元素不会插入
s.insert(5);
s.insert(2);

// 遍历一定是升序
for(int x : s) cout << x << " ";   // 输出 1 2 3 5

// 查找(O(log n))
if (s.count(3)) cout << "有3\n";
auto it = s.find(5);
if (it != s.end()) cout << *it << endl;

// 删除
s.erase(3);           // 删除值为3的元素

multiset 允许重复元素,其余用法几乎一样。

六、unordered_set(哈希表,平均 O(1) 查找)

#include <unordered_set>

unordered_set<string> us;
us.insert("apple");
us.insert("banana");
us.insert("apple");     // 不会重复插入

// 判断是否存在(最快!)
if (us.count("apple")) {
    cout << "有苹果\n";
}

// 遍历顺序是随机的(哈希桶顺序)
for(const auto& fruit : us) {
    cout << fruit << " ";
}

unordered_set vs set 选择口诀

  • 只关心“是否存在”,不在乎顺序 → unordered_set(更快)
  • 需要自动排序、范围查询、lower_bound → set
  • 元素是自定义类型 → 必须提供 hash 函数和 == 运算符(或用 unordered_set 时自己特化)

快速总结:初学者“一句话选容器”

需求推荐容器
普通数组,想自动扩容vector
字符串操作string
需要频繁头尾插入/删除deque
需要频繁中间插入/删除list
需要自动去重 + 排序set
只关心是否存在(最快判断)unordered_set
允许重复但要排序multiset

最后建议的学习顺序(最有效率)

  1. vector + string(练 7 天)
  2. deque(了解即可)
  3. set / unordered_set(练判断存在、去重)
  4. list(真正用到再深入)

祝你早日把这六个容器用得顺手!

有哪个容器你现在最想看更详细的代码例子?
(比如 vector 扩容原理、unordered_set 自定义 hash、set 的 lower_bound 用法、list 的 splice 等)
直接告诉我,我马上给你针对性代码 + 说明~

文章已创建 4893

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

相关文章

开始在上面输入您的搜索词,然后按回车进行搜索。按ESC取消。

返回顶部