C++迭代器失效的避坑指南
1. 什么是迭代器失效?
在 C++ 中,迭代器(iterator) 是一種類似指針的對象,用于遍歷 STL 容器(如 vector、list、map 等)。
迭代器失效是指在對容器進(jìn)行某些操作(如插入、刪除)后,原本有效的迭代器變得不可用,繼續(xù)使用它會導(dǎo)致 未定義行為(Undefined Behavior, UB),如程序崩潰、數(shù)據(jù)錯誤等
2. 哪些操作會導(dǎo)致迭代器失效?
不同的容器有不同的迭代器失效規(guī)則,本文主要討論 vector 的迭代器失效問題。
2.1 vector 的插入操作(push_back, insert)
當(dāng)向 vector 插入元素時:
- 如果
size() == capacity()(容量已滿):vector會重新分配更大的內(nèi)存,并拷貝原有數(shù)據(jù)。- 所有迭代器失效(包括
begin(),end()等)。
- 如果
size() < capacity()(容量未滿):- 插入點(diǎn)之前的迭代器仍然有效。
- 插入點(diǎn)及之后的迭代器失效(因為元素可能被移動)。
示例:push_back 導(dǎo)致迭代器失效
vector<int> v = {1, 2, 3};
auto it = v.begin(); // it 指向 1
v.push_back(4); // 可能觸發(fā)重新分配內(nèi)存
cout << *it; // ? 危險!it 可能失效如何避免?
- 提前預(yù)留空間(
reserve()):
vector<int> v; v.reserve(100); // 預(yù)留 100 個元素的空間 auto it = v.begin(); v.push_back(1); // 不會重新分配,it 仍然有效
- 使用索引代替迭代器(如果允許)。
2.2 vector 的刪除操作(erase, pop_back)
當(dāng)從 vector 刪除元素時:
- 被刪除元素的迭代器失效。
- 被刪除元素之后的所有迭代器失效(因為后面的元素會向前移動)。
- 刪除點(diǎn)之前的迭代器仍然有效。
示例:erase 導(dǎo)致迭代器失效
vector<int> v = {1, 2, 3, 4};
auto it = v.begin() + 2; // it 指向 3
v.erase(v.begin() + 1); // 刪除 2
cout << *it; // ? 危險!it 已經(jīng)失效(3 已經(jīng)前移)如何正確刪除?
- 使用
erase的返回值(返回下一個有效迭代器):
vector<int> v = {1, 2, 3, 4};
auto it = v.begin();
while (it != v.end()) {
if (*it % 2 == 0) {
it = v.erase(it); // 刪除并更新 it
} else {
it++; // 否則正常遞增
}
}反向遍歷(避免迭代器失效)
for (auto it = v.rbegin(); it != v.rend(); ) {
if (*it % 2 == 0) {
it = vector<int>::reverse_iterator(v.erase(it.base() - 1));
} else {
it++;
}
}3. 其他容器的迭代器失效情況
| 容器 | 插入操作(insert) | 刪除操作(erase) |
|---|---|---|
vector | 可能失效(取決于容量) | 被刪除及后面的失效 |
deque | 可能失效(首尾安全) | 被刪除及附近的失效 |
list | 不會失效 | 僅被刪除的失效 |
map/set | 不會失效 | 僅被刪除的失效 |
4. 總結(jié)
vector插入時:- 可能失效(如果觸發(fā)重新分配)。
- 避免方法:提前
reserve()或使用索引。
vector刪除時:- 被刪除及后面的迭代器失效。
- 正確做法:使用
erase返回值或反向遍歷。
- 其他容器(如
list、map)通常更安全,但仍需謹(jǐn)慎。
最佳實踐:
- 避免在遍歷時直接修改容器,除非明確知道迭代器是否有效。
- 盡量使用
range-based for或算法(如remove_if),減少手動管理迭代器。 - 調(diào)試時使用
-D_GLIBCXX_DEBUG(GCC)檢測迭代器錯誤。
以上就是C++迭代器失效的避坑指南的詳細(xì)內(nèi)容,更多關(guān)于C++迭代器失效的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
C++構(gòu)造函數(shù)初始化列表的實現(xiàn)詳解
構(gòu)造函數(shù)主要作用在于創(chuàng)建對象時為對象的成員屬性賦值,構(gòu)造函數(shù)由編譯器自動調(diào)用,無須手動調(diào)用;析構(gòu)函數(shù)主要作用在于對象銷毀前系統(tǒng)自動調(diào)用,執(zhí)行一 些清理工作2022-09-09

