C++迭代器失效的避坑指南
1. 什么是迭代器失效?
在 C++ 中,迭代器(iterator) 是一種類(lèi)似指針的對(duì)象,用于遍歷 STL 容器(如 vector、list、map 等)。
迭代器失效是指在對(duì)容器進(jìn)行某些操作(如插入、刪除)后,原本有效的迭代器變得不可用,繼續(xù)使用它會(huì)導(dǎo)致 未定義行為(Undefined Behavior, UB),如程序崩潰、數(shù)據(jù)錯(cuò)誤等
2. 哪些操作會(huì)導(dǎo)致迭代器失效?
不同的容器有不同的迭代器失效規(guī)則,本文主要討論 vector 的迭代器失效問(wèn)題。
2.1 vector 的插入操作(push_back, insert)
當(dāng)向 vector 插入元素時(shí):
- 如果
size() == capacity()(容量已滿):vector會(huì)重新分配更大的內(nèi)存,并拷貝原有數(shù)據(jù)。- 所有迭代器失效(包括
begin(),end()等)。
- 如果
size() < capacity()(容量未滿):- 插入點(diǎn)之前的迭代器仍然有效。
- 插入點(diǎn)及之后的迭代器失效(因?yàn)樵乜赡鼙灰苿?dòng))。
示例: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; // ? 危險(xiǎn)!it 可能失效如何避免?
- 提前預(yù)留空間(
reserve()):
vector<int> v; v.reserve(100); // 預(yù)留 100 個(gè)元素的空間 auto it = v.begin(); v.push_back(1); // 不會(huì)重新分配,it 仍然有效
- 使用索引代替迭代器(如果允許)。
2.2 vector 的刪除操作(erase, pop_back)
當(dāng)從 vector 刪除元素時(shí):
- 被刪除元素的迭代器失效。
- 被刪除元素之后的所有迭代器失效(因?yàn)楹竺娴脑貢?huì)向前移動(dòng))。
- 刪除點(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; // ? 危險(xiǎn)!it 已經(jīng)失效(3 已經(jīng)前移)如何正確刪除?
- 使用
erase的返回值(返回下一個(gè)有效迭代器):
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 | 不會(huì)失效 | 僅被刪除的失效 |
map/set | 不會(huì)失效 | 僅被刪除的失效 |
4. 總結(jié)
vector插入時(shí):- 可能失效(如果觸發(fā)重新分配)。
- 避免方法:提前
reserve()或使用索引。
vector刪除時(shí):- 被刪除及后面的迭代器失效。
- 正確做法:使用
erase返回值或反向遍歷。
- 其他容器(如
list、map)通常更安全,但仍需謹(jǐn)慎。
最佳實(shí)踐:
- 避免在遍歷時(shí)直接修改容器,除非明確知道迭代器是否有效。
- 盡量使用
range-based for或算法(如remove_if),減少手動(dòng)管理迭代器。 - 調(diào)試時(shí)使用
-D_GLIBCXX_DEBUG(GCC)檢測(cè)迭代器錯(cuò)誤。
以上就是C++迭代器失效的避坑指南的詳細(xì)內(nèi)容,更多關(guān)于C++迭代器失效的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
數(shù)組中求第K大數(shù)的實(shí)現(xiàn)方法
本篇文章是對(duì)數(shù)組中求第K大數(shù)的實(shí)現(xiàn)方法進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-05-05
C++實(shí)現(xiàn)LeetCode(30.串聯(lián)所有單詞的子串)
這篇文章主要介紹了C++實(shí)現(xiàn)LeetCode(30.串聯(lián)所有單詞的子串),本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-07-07
C語(yǔ)言實(shí)現(xiàn)游戲VIP停車(chē)場(chǎng)管理系統(tǒng)
這篇文章主要介紹了C語(yǔ)言實(shí)現(xiàn)游戲VIP停車(chē)場(chǎng)管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-12-12
詳解C++?OpenCV實(shí)現(xiàn)圖像拼接的原理及方法
本文以實(shí)現(xiàn)圖像拼接為目標(biāo),把分割開(kāi)的圖像進(jìn)行拼接還原,核心的內(nèi)容包括:OpenCV圖像拼接相關(guān)原理以及OpenCV圖像拼接案例的實(shí)現(xiàn),感興趣的可以了解一下2022-07-07
C++通過(guò)控制臺(tái)訪問(wèn)deepseek接口并進(jìn)行對(duì)話
這篇文章主要為大家詳細(xì)介紹了C++如何通過(guò)控制臺(tái)訪問(wèn)deepseek接口并進(jìn)行對(duì)話,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2025-02-02
基于C語(yǔ)言實(shí)現(xiàn)迷宮游戲的示例代碼
這篇文章主要介紹了基于C語(yǔ)言如何實(shí)現(xiàn)簡(jiǎn)單的迷宮游戲,對(duì)于學(xué)習(xí)游戲開(kāi)發(fā)的朋友相信有一定的借鑒價(jià)值,需要的朋友可以參考下2022-05-05
C語(yǔ)言數(shù)組實(shí)現(xiàn)學(xué)生信息管理系統(tǒng)設(shè)計(jì)
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言數(shù)組實(shí)現(xiàn)學(xué)生信息管理系統(tǒng)設(shè)計(jì),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-01-01
C++?IO設(shè)備讀寫(xiě)功能實(shí)現(xiàn)詳解
C++的文件IO(Input,Output)操作就是指對(duì)文件進(jìn)行讀寫(xiě)(輸入與輸出)的操作。輸入就是從磁盤(pán)上的文件中讀取內(nèi)容到內(nèi)存中。輸出就是將內(nèi)存中的數(shù)據(jù)內(nèi)容輸出或者說(shuō)寫(xiě)入到磁盤(pán)的文件中,這篇文章主要介紹了C++?IO設(shè)備讀寫(xiě)功能實(shí)現(xiàn)2022-11-11

