STL(三)刪除元素 remove erase

2021-10-09 17:28:14 字數 3343 閱讀 6051

stl功能很強大,但是說到刪除元素,不少人會覺得有些上頭。

刪除元素,第一印象可能就是erase和remove。

remove,在stl不止乙個,有全域性std::remove函式,list容器中,還有乙個名為remove的成員函式;兩個函式的名稱完全一樣,很多人傻傻分不清。

有以下幾點區別:

1、std::remove適用於很多容器,list只是其中之一;而list的成員函式remove,既然是成員函式,肯定是它獨享咯!

2、std::remove其實並沒有真正從容器中刪除元素;list的成員函式remove,將list中滿足條件的元素真正刪除了!

這是最重要的兩點,其他類似引數不一樣、返回值不一樣等等,就不贅述了!上**:

templatevoid print_all(const t& rcoll, const char* premind)

templatevoid initdata(t& rvalue);}

int _tmain(int argc, _tchar* ar**)

這裡,因為經常要列印,將列印函式封裝了一下,還封裝了乙個初始化資料的函式,執行結果如下:

顯而易見,std::remove並沒有刪除容器中的元素,但似乎又有些變化。list的成員函式remove,成功刪除元素!

所以,對list來說,直接用其成員函式remove即可!除了remove外,list還有remove_if成員函式,對於簡單刪除元素來說,基本滿足絕大部分要求。

但是!!!vector呢?它沒有remove的成員函式,怎麼辦?

只能從std::remove來想辦法啦!來看看std::remove函式的原型:

有乙個返回值!!!啥意思呢?

說人話就是:返回的是沒有被刪除的最後乙個元素的位置,從first到這個返回值,就是不等於val的所有元素的序列。

請注意上面標紅的那一句,first表示的是容器迭代器的起始位置,換句話說,只要保留從first到返回值這個區間的元素,就能達到我們的目的。再轉換一下思維,如果刪除了從這個返回值到end的元素,是不是就可以了?

如何刪除乙個區間呢?需要另乙個函式,erase!

不管是list容器,還是vector容器,都有成員函式erase,原型如下:

可以說長得一樣,都有兩種形式。

接收乙個迭代器作為引數,表示刪除指定迭代器位置的元素;以[first,last)為區間的兩個迭代器,刪除這個區間內的所有元素。

單引數的暫時先不管,雙引數的似乎可以滿足上面remove的要求,刪除std::remove返回值到end這個區間的所有元素,試試看:

所有其他**都不變,就修改了劃線的那一句,執行結果如下:

果然可以滿足需求!

erase還有乙個單引數的形式,這個也是很多公司面試時經常考的乙個點!

看如下**:

int _tmain(int argc, _tchar* ar**)

print_all(lstint, "erase後:");

system("pause");

return 0;

}

這裡,沒有呼叫std::remove,直接遍歷lstint中的所有元素,刪除值為4的元素。看起來好像很好,可是一執行,程式直接崩潰!

為何?原因就出在這個erase上。

執行完lstint.erase(iter);後,iter這個迭代器就失靈了,在對其做++iter操作,肯定會出現問題。

怎麼辦?看erase函式有個返回值,其解釋如下:

啥意思?最後乙個被刪除的元素的下乙個元素。

ok!問題簡單了,lstint.erase(iter);後iter失靈,但是返回值是被刪除的元素的下乙個,那把返回值賦值給iter,不就行了?

修改程式,如下:

執行後,結果如下:

不崩潰,但結果也不對,還有乙個4沒刪除掉!

為何如此?

原始資料為 1 5 4 4 7 4 2

當遇到第乙個4時,iter = lstint.erase(iter);,第乙個4被刪除,iter賦值後指向第二個4,重新執行迴圈語句,會++iter,iter的指向又變了,到了第二個4之後也就是7的位置。這第二個4,就成了漏網之魚。

如何解決?

分析一下,當iter指向的元素等於指定元素時,執行iter = lstint.erase(iter)後,其實,已經做了一次後移操作,iter指向的就是被刪除元素的後乙個,所以,這時候不應該再++iter,只有當iter指向的元素不等於指定元素時才後移。

很容易看出來,這就是乙個if....else的條件判斷,修改**如下:

這裡,做了兩處修改,一處是從for迴圈裡把++iter去掉了;另一處,是加了一句else ++iter。

執行結果如下:

成功!!

總結一下:

1、如果是list容器,直接呼叫成員函式remove/remove_if刪除元素;

2、呼叫std::remove,想要刪除元素,必須配合erase成員函式才行,將std::remove返回的迭代器至end全部刪除;

3、如果遍歷元素刪除,要小心erase函式,刪除後的迭代器不可用。

安全刪除STL容器元素

stl容器迭代過程中刪除元素技巧 序列容器的erase方法返回值是指向緊接在被刪除元素之後的元素的有效迭代器,可以根據這個返回值來安全刪除元素。vectorc for vector iterator it c.begin it c.end 關聯容器的 erase 方法沒有返回值,被刪除的迭代器失效,...

stl容器迴圈刪除元素總結

程式中有一段 是關於stl迴圈刪除的內容,大體邏輯如下 實際邏輯要複雜的多,不適合用std remove系列函式 int main int argc,char argv auto it vec vec.begin while it vec vec.end it vec return 0 儘管平常都是...

STL容器刪除元素的陷阱

今天看scott meyers大師的stl的用法,看到了我前段時間犯的乙個錯誤,發現我寫的 和他提到錯誤 幾乎一模一樣,有關stl容器刪除元素的問題,錯誤的 如下 std vectormfriendlist std vector iterator iter mfriendlist.begin for...