C/C++迭代器的失效問題詳解
前言
我今天在使用迭代器時發(fā)現(xiàn)了一個問題,這個問題就是我在使用的迭代器時發(fā)現(xiàn)莫名其妙的有越界訪問和獲取的位置跟預(yù)期不符,經(jīng)過一天的排查我發(fā)現(xiàn)不是所有情況下會出現(xiàn)這種問題,而是在容器刪除和擴容時會發(fā)生越界或結(jié)果和預(yù)期不符的情況。
下面是我今天做的一些代碼測試:
Text1
該函數(shù)的功能是把數(shù)組里面的所有偶數(shù)刪除,遍歷方式使用的是迭代器。
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
vector<int> v{ 1, 2, 3, 4, 5, 6 };
auto it = v.begin();
while (it != v.end())
{
if (!(*it % 2))
{
v.erase(it);
}
++it;
}
return 0;
}
當(dāng)我運行起來時發(fā)現(xiàn)有越界訪問和結(jié)果不符合預(yù)期這兩種情況。
我們接著往下看下一個出問題的測試代碼:
Test2
該函數(shù)的功能是想改變指定位置為30
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main(void)
{
vector<int> v{ 1, 2, 3, 4, 5 };
auto pos =find(v.begin(), v.end(), 3);
v.reserve(100);
*pos = 30;
return 0;
}
當(dāng)該程序運行起來我發(fā)現(xiàn)出現(xiàn)了越界問題!
上面的問題我思考了許久都沒想明白于是我開始去網(wǎng)找答案我找了一天看了數(shù)篇文章,終于解開困擾我多天的問題出現(xiàn)上述情況是因為迭代器失效了??!! 。
迭代器失效
迭代器失效并不是說迭代器就是完全失效而是會出現(xiàn)以下兩種情況:
1.迭代器的意義變了
2.迭代器完全失效
情況1是指迭代器沒完全失效只是它表示的意義和原來的意思不同了,如果不做處理的話會導(dǎo)致運行結(jié)果會預(yù)期有偏差。如出現(xiàn)Test1那樣的結(jié)果本來是想把所有偶數(shù)刪掉結(jié)果迭代器失效了導(dǎo)致部分沒刪掉且還有越界訪問風(fēng)險。
那么,這種問題有什么較好的解決方案呢?其實很簡單我們每次進行操作的時候都要更新下迭代器坐標(biāo)即可
Test1修改后
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
vector<int> v{ 1, 2, 3, 4, 5, 6 };
auto it = v.begin();
while (it != v.end())
{
if (!(*it % 2))
{
//由于刪除導(dǎo)致迭代器失效,所以我們重新更新下迭代器即可
it = v.erase(it);
}
else
{
//當(dāng)?shù)鞑皇桥紨?shù)是才移動,如果所有情況都迭代的話會導(dǎo)致迭代器失效
++it;
}
}
return 0;
}
情況2是指迭代器完全不能用了,如果還堅持使用會發(fā)生越界訪問,因為此時的迭代器已經(jīng)是一個野指針了迭代器的底層都是一個指針來維護的,當(dāng)?shù)魍耆б馕吨摰鞒蔀榱艘爸羔槨?/p>
而Test2 是想修改指定位置的值,但是在修改前發(fā)生了一次擴容而該擴容就是導(dǎo)致迭代器失效的罪魁禍?zhǔn)?,因為發(fā)生擴容的話原來的空間會被丟棄重新開辟一段內(nèi)存來使用,而迭代器的底層是一個指針,它還指向之前的內(nèi)存而該內(nèi)存因為被釋放了所以我們沒有了使用權(quán)此時的迭代器也就成為了野指針。
那么,這種問題如何解決呢?其實和上一個問題的解決方案一樣,當(dāng)?shù)骺赡軙l(fā)生變化時我們需要對迭代器進行一個更新確保它是有效的迭代器。
Test2修改后
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main(void)
{
vector<int> v{ 1, 2, 3, 4, 5 };
auto pos =find(v.begin(), v.end(), 3);
//擴容導(dǎo)致迭代器成為野指針
v.reserve(100);
//這時如果還想更改指定位置的值,那么我們需要進行一個迭代器的更新
pos =find(v.begin(), v.end(), 3);
*pos = 30;
return 0;
}
總結(jié)
當(dāng)使用迭代器時只要內(nèi)存或迭代器會發(fā)生變化,那么我們需要對迭代器進行一次更新確保它每次操作都一定是有效的,從而避免迭代器失效造成的越界訪問和預(yù)期不符的情況。
本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
淺談c++構(gòu)造函數(shù)問題,初始化和賦值問題
下面小編就為大家?guī)硪黄獪\談c++構(gòu)造函數(shù)問題,初始化和賦值問題。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2016-12-12
C++實現(xiàn)PatchMatch圖像修復(fù)算法
這篇文章主要介紹了C++實現(xiàn)PatchMatch圖像修復(fù)算法,本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-04-04

