std::vector 迭代越界崩溃主因是循环中删除元素致 size() 动态变化;正确做法:删元素用迭代器 erase() 或倒序索引,只读用范围 for。

for 循环写法不对,std::vector 迭代时越界崩溃
常见现象是程序运行到某次循环突然 std::out_of_range 或直接段错误。根本原因常是把 size() 当成固定值用,却在循环体里删了元素,导致后续 i 超出新长度。
正确做法是:遍历时不依赖 size() 的中间结果;删元素优先用迭代器 + erase(),或倒序索引遍历。
- 正向遍历删元素?用
auto it = vec.begin(); it != vec.end();配合it = vec.erase(it) - 只读遍历?优先用范围
for:for (const auto& x : vec) - 必须用索引且可能删元素?改用
for (int i = vec.size() - 1; i >= 0; --i)
range-based for 和传统 for 在 std::map 中行为差异
传统 for (int i = 0; i 根本不能用于 <code>std::map —— 它没有连续下标,m[i] 是插入操作,不是访问。
想安全遍历键值对,只能用范围 for 或迭代器。但注意:范围 for 默认按 key 升序(红黑树特性),且每次取的是 std::pair<const key value></const>。
立即学习“C++免费学习笔记(深入)”;
- 取 key 和 value:
for (const auto& [k, v] : m)(C++17 结构化绑定) - 只读 key:
for (const auto& p : m) { p.first; } - 需要修改 value?用
auto& p : m,再改p.second
for 循环中变量作用域搞错,引发未定义行为
比如写 for (int i = 0; i ,然后把 <code>p 存起来——i 每次迭代都析构,p 成悬垂指针。
更隐蔽的是在 lambda 捕获中引用循环变量:[&i]() { return i; },lambda 执行时 i 早已结束生命周期。
- 要保存值?捕获值:
[i]() { return i; }或显式复制:int j = i; int* p = &j; - 需多次复用对象?把变量提到循环外,再在循环内赋值
- 用
std::vector存对象?确保类型可拷贝/移动,别存局部地址
性能陷阱:for 循环里反复调用 strlen() 或 size()
像 for (int i = 0; i 这种写法,每次迭代都从头扫字符串,O(n²) 时间复杂度。编译器几乎不会帮你优化掉这个调用。
即使 std::vector::size() 是 O(1),某些调试模式或自定义容器也可能有开销;更重要的是语义清晰性——你真正关心的是“初始长度”,不是“当前长度”。
- 提前缓存:
const size_t len = std::strlen(s); for (size_t i = 0; i - 用范围
for自动规避:for (char c : str) - 注意
size()返回无符号类型,和有符号int混用可能触发隐式转换警告或逻辑翻转
循环结构本身简单,但和容器生命周期、迭代器失效、类型推导、优化边界这几个点一碰,就容易出静默 bug。尤其在多人协作或重构旧代码时,for 循环里那几行看似安全的访问,往往是 crash 日志里最晚被怀疑、最早该检查的地方。











