迭代器失效指其指向内存不再对应原元素,vector插入/扩容时所有迭代器均失效;erase后旧迭代器及之后全部失效,正确写法为it = vec.erase(it);string类似vector,deque中间操作会使所有迭代器失效;end()也会失效,应每次调用或改用范围for。

迭代器失效不是“迭代器坏了”,而是它指向的内存位置已经不再对应你期望的那个元素了——可能被释放、被移动、甚至被覆盖。对 vector 来说,it 本质上就是 T*,地址一变,*it 就是未定义行为,崩溃或静默出错都可能发生。
vector 插入/扩容时所有迭代器都可能失效
只要触发了内存重分配(比如 push_back 时 size() == capacity()),begin()、end()、中间任意 it 全部失效。这是因为底层调用 allocate → 搬移数据 → deallocate,旧指针指向的内存已被释放。
-
reserve(n)可以提前预留空间,避免后续多次push_back触发重分配 - 不要在循环中一边
push_back一边用旧it解引用或自增 - 如果必须边插边用,插完立刻重新取
it = vec.begin() + offset,别复用老迭代器
vector erase 后继续用旧迭代器会越界或崩溃
erase(it) 不仅让 it 失效,还会让 it 之后所有迭代器失效(因为后面元素前移)。更危险的是:很多人写 erase(it++),这等于先用 it,再 ++it,但 ++ 操作本身依赖 it 的有效性——而 it 已经被删掉了。
- 正确写法是
it = vec.erase(it),它返回下一个有效位置 - 循环结构必须改成
for (auto it = vec.begin(); it != vec.end(); ),不能带++it在 for 头里 - 批量删除优先用
std::remove_if+erase,避免反复搬移
string 和 deque 的迭代器失效规则容易被低估
std::string 自 C++11 起要求字符连续存储,所以它的迭代器和 vector<char></char> 行为高度一致:+= 或 append 触发扩容时,所有迭代器立即失效;即使没扩容,插入/删除也会导致插入点及之后迭代器失效。
立即学习“C++免费学习笔记(深入)”;
-
deque更隐蔽:头尾插入/删除通常不失效迭代器(但可能失效引用),一旦在中间insert或erase,所有迭代器全部失效 - 别假设
deque像list一样安全——它分段连续,中间操作代价高且破坏性强 - 如果需要频繁中间修改又想保迭代器,直接换
list或forward_list
最常被忽略的一点是:end() 迭代器本身也参与失效判定。很多代码缓存 auto last = vec.end() 然后在循环里比较 it != last,但只要容器被修改,last 就可能已失效——哪怕 it 还活着。安全做法永远是每次比较都调用 vec.end(),或者用基于范围的 for 避免手动管理迭代器。


















