C++中vector迭代器失效問題的原因及解決方案
一、迭代器失效是什么
在進入此問題時,我們首先要了解迭代器的本質其實是指針,迭代器的失效就相當于指針失效的問題。而指針失效就說明指針指向的空間是非法的,變成為了野指針。
空間非法: 就是指指針指向了已經被釋放的空間或者越界訪問,
我們可以用代碼的方式來解釋此問題。
#include<iostream> #include<vector> using namespace std; void test() { vector<int> v; v.push_back(1); v.push_back(2); v.push_back(3); v.push_back(4); auto it = v.begin(); v.push_back(5); while (it != v.end()) { cout << *it << " "; ++it; } cout << endl; }
通過上述代碼,當我們運行程序時會發(fā)生報錯。其原因就是因為迭代器失效的問題。我們可以分析一下其中的過程。
過程:it一開始指向初始空間的元素,而再次進行尾插操作時,由于空間不夠需要擴容,因此需要釋放舊空間開辟新空間,但此時的it還是指向已經被釋放的舊空間,已經成為野指針了,因此再循環(huán)當中對野指針進行解引用是就會導致程序崩潰。
二、vector中哪些操作會導致迭代器失效
在所有可能對空間進行擴容操作的都有可能導致迭代器失效,如:push_back、resize、insert、reserve等。
需要注意的是:有一個特殊的操作,編譯器也會認為迭代器失效,就是erase操作。
我們要知道,erase函數的返回值是返回被刪除元素的后一個位置,當刪除完元素時,當前位置之后的元素都會往前進行偏移,但這并沒有導致空間的改變,理論上這是不是并沒有導致迭代器失效呢?
那么如果當前位置的元素剛好就是最后一個元素時,當對其進行刪除時,返回的位置則指向end(),而end()的位置并沒有元素,那么當對其進行解引用時也會導致程序崩潰,因此編譯器認為這樣的操作并不安全,于是認為當刪除完元素時,迭代器就應該按失效的方式處理,不再對其進行使用。
#include<iostream> #include<vector> using namespace std; void test() { vector<int> v{1,2,3,4,5,6}; auto it = v.begin(); //刪除偶數 while (it != v.end()) { if (*it % 2 == 0) { v.erase(it); } else { it++; } } }
三、如何避免迭代器失效的問題
通過以上敘述,我們了解了有關迭代器失效的產生及問題,那么我們該如何避免此問題發(fā)生呢?
其實解決辦法也挺簡單的:只需當我們使用了有可能對迭代器失效的操作時,如果想再次使用迭代器時,只需在使用前令其指向新空間。
我們可以用一段代碼來演示過程:
舉例:使用push_back函數
#include<iostream> #include<vector> using namespace std; void test() { vector<int> v; v.push_back(1); v.push_back(2); v.push_back(3); v.push_back(4); auto it = v.begin(); v.push_back(5); it = v.begin(); while (it != v.end()) { cout << *it << " "; ++it; } cout << endl; }
通過上述代碼,當我們要再次進行尾插操作時,只需改變一下it指向新空間的位置即可,這樣就不會導致迭代器產生失效的問題了。
到此這篇關于C++中vector迭代器失效問題的原因及解決方案的文章就介紹到這了,更多相關C++ vector迭代器失效內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
C++實現LeetCode(158.用Read4來讀取N個字符之二 - 多次調用)
這篇文章主要介紹了C++實現LeetCode(158.用Read4來讀取N個字符之二 - 多次調用),本篇文章通過簡要的案例,講解了該項技術的了解與使用,以下就是詳細內容,需要的朋友可以參考下2021-07-07