std::list 声明需指定元素类型,不支持下标访问;常用初始化有空构造、初始化列表、拷贝及迭代器区间构造;push_front/push_back为O(1)头尾插入,insert需迭代器位置且返回新元素迭代器;遍历必须用迭代器或范围for,因链表内存不连续,无operator[]。
怎么声明和初始化一个
直接用
模板,指定元素类型即可。它不支持随机访问,所以别指望用下标
取值。
常见初始化方式:
—— 空链表
—— C++11 初始化列表(最常用)
—— 拷贝构造
—— 迭代器区间构造
注意:不能像
那样用
构造 10 个 5,
的构造函数不支持这种“数量+值”重载(C++11 起才加入,但很多旧项目或编译器仍不默认启用,容易误报错)。
、
和
怎么选
和
是 O(1) 插入,适合在头尾追加;
必须传迭代器位置,且只能插入到该位置之前(不是“替换”)。
立即学习
“
C++免费学习笔记(深入)
”;
关键细节:
等价于
等价于
若想在第 3 个位置插入(即索引为 2),得先用
获取迭代器——
不支持
返回新插入元素的迭代器,可用于连续插入:
别对失效迭代器调用
:
的插入/删除只使**对应迭代器**失效,其他迭代器仍有效(这是它比
更适合频繁中间操作的原因)。
遍历和查找为什么不能用下标,而要用迭代器
是双向链表,内存不连续,
和
根本不存在。强行写
会编译失败,错误信息类似:
。
C知道
CSDN推出的一款AI技术问答工具
下载
正确遍历方式只有迭代器(或范围 for):
查找必须配合算法:
。别手写循环找——虽然可行,但语义不清,且容易忽略
判断。
性能提醒:
是 O(n),没有“哈希加速”,如果需要高频查找,
本身就不合适,应换
或加索引结构。
删除元素时
和
有什么区别
删除**迭代器指向的单个节点**(或迭代器区间),返回下一个有效迭代器;
是成员函数,删除**所有等于某值的节点**(不返回迭代器,也不保证顺序,但保持剩余元素相对顺序)。
典型误用:
❌ 编译失败 ——
不接受值,只接受迭代器
✅ 正确,删掉所有大于 10 的元素
循环中删除要小心:
—— 必须用
返回值更新
,否则迭代器失效后继续
是未定义行为
还有一个易忽略点:
不改变容器大小?错。它确实删除节点、调用析构、减小
,但它不释放内存(
的节点分配是离散的,没“capacity”概念,所以无所谓释放)。
真正复杂的是带条件的批量删除和迭代器稳定性——只要不用错
返回值,就基本不会崩;但一旦混用
和手动
,逻辑容易绕晕。
std::liststd::list[]std::list lst; std::list lst = {1, 2, 3}; std::list lst(other_lst); std::list lst(other_lst.begin(), other_lst.end()); vectorlist(10, 5) listpush_frontpush_backinsertpush_frontpush_backinsertlst.insert(lst.begin(), 42)lst.push_front(42)lst.insert(lst.end(), 42)lst.push_back(42)std::next(lst.begin(), 2)listlst[2]insertauto it = lst.insert(pos, 1); lst.insert(it, 2);insertlistvectorstd::listoperator[]at()lst[5]error: no match for 'operator[]'for (auto it = lst.begin(); it != lst.end(); ++it) {
std::cout << *it << " ";
}
// 或更简洁:
for (const auto& x : lst) {
std::cout << x << " ";
}std::find(lst.begin(), lst.end(), 42)end()std::findlistunordered_seteraseremoveeraseremovelst.erase(5)eraselst.remove_if([](int x) { return x > 10; })for (auto it = lst.begin(); it != lst.end(); ) { if (*it == 0) it = lst.erase(it); else ++it; }eraseit++itremovesize()listeraseremoveerase