必须用容器的begin()和end()获取合法迭代器范围;end()指向末尾后一位置,不可解引用,仅用于比较;直接取地址如&v[0]对list或空容器可能崩溃。

用 begin() 和 end() 获取合法迭代器范围
迭代器不是指针,但行为类似;直接取地址或硬写 &v[0] 可能崩溃,尤其对 std::list 或空容器。必须用容器提供的 begin() / end() 成员函数——它们保证返回类型正确、行为定义良好。
-
end()指向“末尾之后一个位置”,不可解引用,只用于比较;常见错误是写成it - 空容器时
begin() == end()为真,循环会直接跳过,这是预期行为 - 使用
auto推导类型最安全:for (auto it = v.begin(); it != v.end(); ++it)
遍历时修改容器导致迭代器失效的典型场景
只要容器内存重排(如 std::vector 扩容)、节点被删(std::list)、或元素移动(std::deque),原有迭代器立刻失效。继续用它读写就是未定义行为,可能 crash 或静默出错。
-
vector.push_back()可能触发 reallocation → 所有迭代器失效 -
list.erase(it)后,it失效,但erase()返回下一个有效迭代器,应写成it = lst.erase(it) - 想边遍历边删,优先用
remove_if + erase惯用法,避免手写循环
const_iterator 与 auto 的隐式转换陷阱
对 const 容器调用 begin() 返回 const_iterator;但若用 auto it = container.begin(),且容器本身是 const,则 it 就是 const_iterator,此时 *it = x 编译失败——不是语法错,是类型不允许。
- 不要假设
auto总给你可写的迭代器;检查容器是否 const、是否用了cbegin() - 需要统一写法时,显式声明:
std::vector<int>::const_iterator cit = v.cbegin()</int> -
cbegin()/cend()在 C++11 起可用,比 const_cast 更清晰
range-based for 循环 vs 手写迭代器循环的选择依据
90% 场景用 range-based for 更简洁安全,但某些操作必须用传统迭代器:获取当前索引、需要 erase() 返回值、或处理两个容器同步遍历。
立即学习“C++免费学习笔记(深入)”;
- 要索引?用
for (size_t i = 0; i ,别靠 <code>it - v.begin()算——list不支持随机访问 - 双容器遍历?确保 size 相同且用相同类型迭代器,否则
it1 != it2比较无意义 - 性能上,现代编译器对两种写法优化程度接近,不用刻意“手写迭代器”图快
迭代器失效和类型匹配是最容易在调试后期才暴露的问题,尤其跨函数传参或模板泛化时,const 修饰和容器可变性稍不注意就会让行为突然改变。











