一起來學(xué)習(xí)C++中remove與erase的理解
erase 簡介
vector
中 erase
函數(shù)原型如下:
iterator erase( const_iterator position); iterator erase( const_iterator first, const_iterator last);
用于刪除 vector 容器中的一個(gè)或者一段元素。
在刪除一個(gè)元素的時(shí)候,其參數(shù)為指向相應(yīng)元素的迭代器;而在刪除一段元素的時(shí)候,參數(shù)為指向一段元素的開頭的迭代器以及指向結(jié)尾元素的下一個(gè)元素的迭代器。
調(diào)用 erase
后,vector
元素會(huì)向前移,因此需要格外注意這個(gè)特征,避免越界訪問以及漏處理。
示例代碼:
int main(int argc, char *argv[]) { vector<int> myVector; myVector.push_back(1); myVector.push_back(2); myVector.push_back(3); myVector.push_back(3); myVector.push_back(3); myVector.push_back(4); myVector.push_back(3); myVector.push_back(3); myVector.push_back(3); for (vector<int>::iterator itr = myVector.begin(); itr != myVector.end(); itr++) { if (*itr == 3) { //此時(shí)itr已經(jīng)指向了新的下一個(gè)元素;如果不執(zhí)行itr--與itr++做抵消,則會(huì)超出end導(dǎo)致崩潰。 itr = myVector.erase(itr); itr--; } } cout << "[After erase] myVector: "; for (int temp : myVector) cout << temp << " "; cout << endl; return 0; }
remove 簡介
algorithm
中 remove
原型如下:
template<class ForwardIterator, class Type> ForwardIterator remove( ForwardIterator first, ForwardIterator last, const Type& value); template<class ExecutionPolicy, class ForwardIterator, class Type> ForwardIterator remove( ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, const Type& value);
remove
函數(shù)是由 STL
庫中 algorithm
提供的一個(gè)函數(shù),這里的 remove
字面意思很容易引起初學(xué)者誤解。因?yàn)檎{(diào)用以后并非真實(shí)的 remove
。
代碼示例
#include <vector> #include <iostream> #include <algorithm> using namespace std; int main(int argc, char *argv[]) { vector<int> array; array.push_back(1); array.push_back(2); array.push_back(3); array.push_back(3); array.push_back(4); array.push_back(5); cout << "init : "; print(array); array.erase(array.begin()); cout << "erase array.begin() :"; print(array); vector<int>::iterator remove2It = remove(array.begin(), array.end(), 2); cout << "remove 2 : "; print(array); cout << "remove2It traverse : "; for (; remove2It != array.end(); remove2It++) cout << *remove2It << " "; cout << endl; vector<int>::iterator remove3It = remove(array.begin(), array.end(), 3); cout << "remove 3 : "; print(array); cout << "remove3It traverse : "; for (; remove3It != array.end(); remove3It++) cout << *remove3It << " "; cout << endl; return 0; }
運(yùn)行后打印如下:
init : 1 2 3 3 4 5
erase array.begin() :2 3 3 4 5
remove 2 : 3 3 4 5 5
remove2It traverse : 5
remove 3 : 4 5 5 5 5
remove3It traverse : 5 5
代碼分析
如上所示,執(zhí)行 array.erase(array.begin());
后,符合預(yù)期地將第一個(gè)元素刪除了,打印結(jié)果為:erase array.begin() : 2 3 3 4 5
。
在此基礎(chǔ)(2 3 3 4 5
)上執(zhí)行 remove(array.begin(), array.end(), 2);
,可能慣性思維會(huì)覺得得到的結(jié)果(這個(gè)是錯(cuò)誤的結(jié)果,效果就像調(diào)用了 erase 一樣)應(yīng)該是 3 3 4 5
,4 個(gè)元素。而實(shí)際打印結(jié)果為:3 3 4 5 5
,5 個(gè)元素。這里完全“顛覆”了對(duì) remove 這一字義的認(rèn)識(shí)。
remove 是如何工作的?
查找資料后發(fā)現(xiàn),remove
和 erase
存在很大的區(qū)別。
remove
是 algorithm
的模板函數(shù),它接收的都是迭代器參數(shù),并不接收某個(gè)容器。remove
并不知道它作用于哪個(gè)容器,也不可能發(fā)現(xiàn)容器,因?yàn)闆]有辦法從一個(gè)迭代器獲得對(duì)應(yīng)于它的容器。
想要從容器中刪除一個(gè)元素,唯一的方法就是調(diào)用容器的一個(gè)成員函數(shù),比如 erase
函數(shù)。而 remove
無法知曉,故不可能根據(jù)一個(gè)傳進(jìn)來的迭代器進(jìn)而在該容器中除去元素。因此,調(diào)用 remove
后并不會(huì)改變?cè)撊萜鞯脑貍€(gè)數(shù)。
得出的結(jié)論是:remove
并不是真的在刪除元素,因?yàn)樗咀霾坏?/strong>。
remove 的工作流程
(注意:begin
與 end
是左閉右開區(qū)間,即 end
是 vector
之外了,即 vector
最后一個(gè)元素的下一個(gè)。)
這里需要明確一點(diǎn)是,remove()
的返回值是一個(gè) iterator
。
再來看 remove(3) 的過程:
至此,大概可以弄清楚 remove
這個(gè)函數(shù)對(duì)一個(gè) vector
做了哪些操作,改變了哪些元素的順序,以及返回值是指向何處。
總結(jié)
本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
C/C++?Qt數(shù)據(jù)庫與SqlTableModel組件應(yīng)用教程
SqlTableModel?組件可以將數(shù)據(jù)庫中的特定字段動(dòng)態(tài)顯示在TableView表格組件中,這篇文章將主要介紹SqlTableModel組件一些常用的操作,需要的朋友可以參考一下2021-12-12C++實(shí)現(xiàn)銀行排隊(duì)系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)銀行排隊(duì)系統(tǒng),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-07-07Qt?TCP網(wǎng)絡(luò)通信學(xué)習(xí)
用于數(shù)據(jù)傳輸?shù)牡蛯泳W(wǎng)絡(luò)協(xié)議,多個(gè)物聯(lián)網(wǎng)協(xié)議都是基于TCP協(xié)議的,這篇文章為大家介紹了Qt?TCP網(wǎng)絡(luò)通信,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-08-08