在使用std的容器的時候,不少人喜歡用vector, 因為比起list,更省空間,而且可以根據(jù)index直接讀取某個值,而不用一個個枚舉來取.
但是,std::vector確實有一些值得注意的陷阱, 這里先說其中一個, 請看以下代碼.
std::vector< int > values;
values.push_back(1);
values.push_back(2);
values.push_back(3);
values.erase(values.begin() + 1);
乍看之下,這幾行簡單的代碼沒什么 問題. 實際執(zhí)行起來, 還是沒什么問題 , 但卻有一個陷阱. 由于例子里面用的是int的vector,所以這樣做沒有任何問題, 但,假如不是一個int, 而是一個類,一個結(jié)構(gòu)體,類或結(jié)構(gòu)體里面還有指針, 那就很可能出問題了. why?
因為vector不象list,vector始終要保持一個完整的內(nèi)存結(jié)構(gòu)(因為就是一個數(shù)組),這樣才可以讓values[1]這樣的方式正確運行. 但是,如果要在vector中間刪掉一個成員的話,vector是這樣做的, 先把該成員后面的一個成員,一直到最后一個成員往前一位置拷貝,這樣需要刪除的成員已經(jīng)被后面的覆蓋了, 然后再刪除最后一個成員,這樣,vector又能保持一段完整的內(nèi)存結(jié)構(gòu)了. 注意,因為最后一個成員會被刪除,而如果這個成員里面有一個成員變量是指針, 那析構(gòu)函數(shù)很有可能會把這個指針指向的地方釋放掉! 這樣,即使最后一個成員被復制了一份 到倒數(shù)第2的位置,也因為在他本身被刪除的時候,把倒數(shù)第2個(也就是它的復制) 的指針成員所指向的地方給釋放了! 如圖:

解決的辦法也很簡單, 最少有2種. 1, 增加作為vector類型的類的拷貝構(gòu)造函數(shù), 因為vector在erase的時候會發(fā)生一次拷貝,讓拷貝構(gòu)造函數(shù)不單單是復制指針,還把指針所指向的內(nèi)容給拷貝一份,這樣就不會導致被最后一個成員釋放的時候一起釋放掉了. 2, 如果有引用記數(shù)的話,如智能指針, 就不會被釋放掉了。不過如果一般編碼里面不需要用到引用記數(shù)的話,還是方法1比較簡便