1. Vector迭代器失效的本质原因
在C++ STL中,vector是最常用的顺序容器之一,它采用动态数组实现,提供了快速的随机访问能力。但正是这种底层实现方式,导致了迭代器失效问题的频繁出现。
vector的迭代器本质上是一个原生指针(或类指针对象),它直接指向容器中的某个元素。当vector发生以下三种操作时,会导致迭代器失效:
- 插入元素(insert/push_back):当vector容量不足时,会重新分配内存,导致所有迭代器失效;即使容量足够,插入点后的迭代器也会失效
- 删除元素(erase/pop_back):被删除元素之后的所有迭代器都会失效
- 扩容操作(reserve/resize):任何导致内存重新分配的操作都会使所有迭代器失效
cpp复制vector<int> v = {1,2,3,4,5};
auto it = v.begin() + 2; // 指向元素3
v.push_back(6); // 可能导致迭代器it失效
cout << *it; // 未定义行为!
注意:迭代器失效并不意味着指针一定会变成野指针,而是说使用这个迭代器的行为是未定义的。在某些实现中它可能"碰巧"还能工作,但这绝对不能依赖。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 典型失效场景与危险示例
2.1 遍历时删除元素
这是最常见的迭代器失效场景,也是新手最容易犯的错误:
cpp复制vector<int> v = {1,2,3,4,5};
for(auto it = v.begin(); it != v.end(); ++it) {
if(*it % 2 == 0) {
v.erase(it); // 危险!erase后it失效,再++会导致未定义行为
}
}
这段代码在VS调试模式下通常会触发断言错误,而在release模式下可能导致程序崩溃或产生错误结果。
2.2 容量变化导致的失效
vector的扩容策略因实现而异,但通常采用指数增长(如MSVC是1.5倍,GCC是2倍):
cpp复制vector<int> v = {1,2,3};
auto it = v.end();
v.push_back(4); // 可能触发扩容
cout <
