跳转到主内容
websoft网络软件专家 - 深耕网络技术,打造实用软件!

C++ list怎么用 C++双向链表容器常用操作详解【STL】

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

相关文章