STL容器 erase的使用陷井

http://www.cppblog.com/beautykingdom/archive/2008/07/09/55760.aspx?opt=adminios

在STL(標準模板庫)中常常會碰到要刪除容器中部分元素的狀況,本人在編程中就常常編寫這方面的代碼,在編碼和測試過程當中發如今STL中刪除容器有不少陷阱,網上也有很多網友提到如何在STL中安全刪除元素這些問題。本文將討論編程過程當中最常用的兩個序列式容器vector、list中安全刪除元素的方法和應該注意的問題,       其它如queue、stack等配接器容器(container adapter),因爲它們有專屬的操做行爲,沒有迭代器(iterator),不能採用本文介紹的刪除方法,至於deque,它與vector的刪除方法同樣。STL容器功能強大,but no siliver bullet,若是你使用不當,也將讓你吃盡苦頭。
    這裏最重要的是要理解erase成員函數,它刪除了itVect迭代器指向的元素,而且返回要被刪除的itVect以後的迭代器,迭代器至關於一個智能指 針,指向容器中的元素,如今刪除了這個元素,將致使內存從新分配,相應指向這個元素的迭代器以後的迭代器就失效了,但erase成員函數返回要被刪除的 itVect以後的迭代器。  程序員

1.手工編寫for循環代碼刪除STL序列式容器中元素的方法
例如,你能看出如下代碼有什麼問題?
例1:
#include <iostream>
#include <vector>
using namespace std;
void main( ) {
       vector<int> vectInt;
       int i;
       //     初始化vector容器
       for (i = 0; i < 5; i++ ) {
               vectInt.push_back( i );
       }
       //     如下代碼是要刪除全部值爲4的元素
       vector<int>::iterator itVect = vectInt.begin();
       for ( ; itVect != vectInt.end();   ++itVect ) {
               if ( *itVect == 4 ) {
                     vectInt.erase( itVect );
               }
       }
       int iSize = vectInt.size();
       for (   i = 0 ; i < iSize; i++ )   {
                     cout << " i= " << i <<   ", " << vectInt[ i ] << endl;
       }
} 算法

    例1將致使程序未定義的錯誤,在windows中便是訪問非法內存,程序當掉。由於vectInt.erase( itVect );調用後itVect以後的迭代器已無效了,因此當執行++itVect後,*itVect訪問了非法內存。例1也是初學者最容易犯的錯誤,這個錯誤也 比較容易發現。

例2:
#include <iostream>
#include <vector>
using namespace std;
void main( ) {
       vector<int> vectInt;
       int i;
       //     初始化vector容器
       for ( i = 0; i < 5; i++ ) {
               vectInt.push_back( i );
               if ( 3 == i ) {
                     //       使3的元素有兩個,而且相臨。這很是關鍵,不然將發現不了bug。
                     //   具體解釋見下。
                     vectInt.push_back( i );
               }
       }
       vector<int>::iterator itVect = vectInt.begin();
       vector<int>::iterator itVectEnd = vectInt.end(); //       防止for多重計算
       //     如下代碼是要刪除全部值爲3的元素
       for ( ; itVect != itVectEnd; ++itVect ) {
               if ( *itVect == 3 ) {
                     itVect = vectInt.erase( itVect );
               }
       }
       int iSize = vectInt.size();
       for (   i = 0 ; i < iSize; i++ )   {
                     cout << " i= " << i <<   ", " << vectInt[ i ] << endl;
       } 編程

例2可能會致使不能把vectInt中全部爲3的元素刪除掉。由於第一次刪除成功時,itVect = vectInt.erase( itVect );itVect爲指向3以後的位置,以後再執行++itVect,itVect就掉過了被刪除元素3以後的元素3,致使只刪除了一個爲3的元素,這個 bug比較隱蔽,由於若是不是兩個均爲3的元素相臨,就將很難捕捉到這個bug,程序有可能在一段時間運行良好,但如碰到容器中兩值相同的元素相臨,則程 序就要出問題。  windows


例3:
#include <iostream>
#include <vector>
using namespace std;
void main( ) {
       vector<int> vectInt( 5 );
       int i;
       vectInt[ 0 ] = 0;
       vectInt[ 1 ] = 1;
       vectInt[ 2 ] = 2;
       vectInt[ 3 ] = 3;
       vectInt[ 4 ] = 4; //     替換爲 vectInt[ 4 ] = 3;試試
       vector<int>::iterator itVect = vectInt.begin();
       vector<int>::iterator itVectEnd = vectInt.end(); //       防止for多重計算
       //     如下代碼是要刪除全部值爲3的元素
       for ( ; itVect != itVectEnd; ) {
               if ( *itVect == 3 ) {
                     itVect = vectInt.erase( itVect );
               }
               else {
                     ++itVect;
               }
       }
       int iSize = vectInt.size();
       for (   i = 0 ; i < iSize; i++ )   {
                     cout << " i= " << i <<   ", " << vectInt[ i ] << endl;
       }
}
例3,對於本例你可能要說程序沒有任何問題,解決了上面的兩個bug,程序也運行正常。但且慢,你把 「vectInt[ 4 ] = 4;」 這一行改成 「vectInt[ 4 ] = 3;」試試,一運行,程序當掉,訪問非法內存!你迷惑不解:從程序看不出bug,並且我還把vectInt.end()放在外面計算以防止for多重計算,提升效率。哈哈,問題就出在最後一句話!算法大師Donald Knuth有一句名言:不成熟的優化是一切惡果的根源( Permature optimization is the root of all evil )。因爲在for循環中要刪除元素,則vectInt.end()是會變化的,因此不能在for循環外計算,而是每刪除一次都要從新計算,因此應放在 for循環內。那你要問,爲何把 「vectInt[ 4 ] = 4;」 這一行改成 「vectInt[ 4 ] = 3;」程序就會當掉,而不改程序就很正常呢?這就跟vector的實現機制有關了。下面以圖例詳細解釋。
vectInt的初始狀態爲:

                                  | end
0   1   2   3   4                                  

刪除3後,

                       |新的end   | 原來的end
0   1   2   4   4     


注意上面「新的end」指向的內存並無被清除,爲了效率,vector會申請超過須要的內存保存數據,刪除數據時也不會把多餘的內存刪除。刪除後多餘內存並無清0。
而後itVect再執行++itVect,由於此時*itVect等於4,因此繼續循環, 這時itVect 等於「新的end」但不等於「原來的end」(它即爲itVectEnd),因此繼續,由於 *itVect訪問的是隻讀內存獲得的值爲4,不等於3,故不刪除,而後執行++itVect此時itVect等於itVectEnd退出循環。從上面過程能夠看出,程序多循環了一次(刪除幾回,就要多循環幾回),但程序正常運行。

若是把 「vectInt[ 4 ] = 4;」 這一行改成 「vectInt[ 4 ] = 3;」過程以下:

                                                                         | end
0         1         2         3         3     安全

  
刪除3後,
                                                                 |新的end       |原來的 end
0         1         2         3         3      

刪除第2個3後,
                                                 |新的end             |原來的 end
0         1         2         3         3      

這時itVect 等於「新的end」但不等於「原來的end」(它即爲itVectEnd),因此繼續,由於 *itVect訪問的是隻讀內存獲得的值爲3,等於3,因此執行刪除,但由於*itVect訪問的是隻讀內存不能刪除,因此程序當掉。

綜上,咱們知道當要刪除的值在容器末尾時,會致使程序刪除非法內存,程序當掉;即便程序正常運行,也是for循環多執行了等於刪除個數的循環。因此把 vectInt.end()放在for循環外面執行,徹底是錯誤的。對於list容器,list.end()在刪除過程當中是不會變的,能夠把它放在for 循環外面計算,但因爲list.end()是個常量,把list.end()放在for循環中計算編譯器應該能夠優化它。從安全考慮,除非你能保證for 循環中不會改變容器的大小,不然都應該對容器的值在for循環中計算,對於 vectInt.size()這樣的計算,也應該在for循環中計算,不要由於微小的優化而致使程序出錯。


正確的方法:
例4:
#include <iostream>
#include <vector>
using namespace std;
void main( ) {
       vector<int> vectInt;
       int i;
       for (   i = 0; i < 5; i++ ) {
               vectInt.push_back( i );
               if ( 3 == i ) {
                     //       使3的元素有兩個,而且相臨。
                     vectInt.push_back( i );
               }
       }
       vector<int>::iterator itVect = vectInt.begin();

       //     如下代碼是要刪除全部值爲3的元素

       for ( ; itVect != vectInt.end();   ) {   // 刪除 ++itVect{

               if ( *itVect == 3 ) {

                     itVect = vectInt.erase( itVect );
               }
               else { 

                     ++itVect;
               }
       }
       //     把vectInt.size()放在for循環中

       for (   i = 0 ; i < vectInt.size(); i++ )   {
                     cout << " i= " << i <<   ", " << vectInt[ i ] << endl;
       }

運行結果爲:
i= 0, 0
i= 1, 1
i= 2, 2
i= 3, 4

從結果顯示值爲3的元素確實被刪除了。

2.使用STL中通用算法或容器成員函數刪除元素的方法
以上手工編寫for循環代碼刪除容器中元素的方法也有一些問題,若是判斷條件特別複雜,又有循環判斷的話,循環中間又有異常處理的話,++itVect的位置就要當心放置了,稍不留意就要出錯。因此手工編寫代碼刪除容器中元素的方法不太安全,代碼重複,也不夠優雅,要注意的地方不少。

對於這種狀況,能夠考慮使用STL中通用算法remvoe()和remove_if()幫忙。而remvoe()和remove_if()這兩個算法也有一個問題須要程序員特別當心。在通用算法中的 remove(包括remove_if)函數,並不真正從容器中刪除元素,而是「應被刪除的元素」被其後的「未被刪除的元素」覆蓋。返回值ForwardIterator指向經移除後的最後元素的下一位置。如vector{0,1,2,3,3,4},執行remove(),但願移除全部值爲3的元素,結果爲{0,1,2,4,3,4},返回值 ForwardIterator指向第5個元素。即:

0         1         2         3         3       4   移除前

0         1         2         4         3       4   移除後


移除值爲3的元素。移除後3被其後的4替代,最後兩位元素爲殘餘數據。

例 5:

void main() {
       vector<int> vectInt;
       int i;
       for (i = 0; i < 5; i++ ) {
               vectInt.push_back( i );
               if ( 3 == i ) {
                     vectInt.push_back( i );
               }
       }
       remove( vectInt.begin(), vectInt.end(), 3 );
       cout << " after deleted , size = " << vectInt.size() << endl;
       for ( i = 0; i < vectInt.size();; i++ ) {
               cout << "i = " << i << " , " << vectInt[i] << endl;
       }
}
運行結果爲:
after deleted , size = 6 // 從這行能夠看出,移除後容器的大小沒變
i = 0 , 0
i = 1 , 1
i = 2 , 2
i = 3 , 4 //   從這行能夠看出:「應被刪除的元素」3 被其後的「未被刪除的元素」4覆蓋
i = 4 , 3
i = 5 , 4     

因此要完全刪除還應該把後面的殘餘數據刪除掉,這能夠經過調用容器的成員函數erase()作到。

例 6:
void main() {
       vector<int> vectInt;
       int i;
       for (i = 0; i < 5; i++ ) {
               vectInt.push_back( i );
               if ( 3 == i ) {
                     vectInt.push_back( i );
               }
       }
       vectInt.erase( remove( vectInt.begin(), vectInt.end(), 3 ), vectInt.end() );
       cout << " after deleted , size = " << vectInt.size() << endl;
       for ( i = 0; i < vectInt.size();; i++ ) {
               cout << "i = " << i << " , " << vectInt[i] << endl;
       }
}

運行結果爲:
after deleted , size = 4 // 從這行能夠看出,刪除後容器的大小變化了
i = 0 , 0
i = 1 , 1
i = 2 , 2
i = 3 , 4
從結果能夠看出,全部值爲3的元素確實被刪除了。
對於vector容器存放其餘比較複雜的對象,就能夠用remove_if()加函數對象(Function Object)的方法。
如:
例7:
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
#include <algorithm>
#include <list>
using namespace std;
class CTest {
public:
       CTest( const string& str, int iPrice ) : m_strName( str ), m_iPrice( iPrice ) { }
       void vPrint() { cout << "name=" << m_strName << " price = " << m_iPrice << endl;
       }
private:
       string m_strName;
       int   m_iPrice;
       //     因爲兩個函數對象要訪問CTest類的private成員,因此設爲友員。
       friend class CStrFunc;
       friend class CIntFunc;
};

//     函數對象,根據string比較
class CStrFunc {
       string m_str;
public:
       CStrFunc( const string& str ) : m_str( str ) {
       }
       bool operator() ( const CTest& left ) {
               return ( m_str == left.m_strName ) ? true : false;
       }
};

//     函數對象,根據int比較
class CIntFunc {
       int m_iPrice;
public:
       CIntFunc( int iPrice ) : m_iPrice( iPrice ) {
       }
       bool operator() ( const CTest& left ) {
               return ( m_iPrice == left.m_iPrice ) ? true : false;
       }
};

void main( ) {

       vector< CTest > vectTest;
       int i;
       for (   i = 0; i < 5 ; i++ ) {
               stringstream stream; //       流格式化符,把int轉化爲string
               stream << i;
               string str = stream.str();
               CTest clTest( str, i );
               vectTest.push_back( clTest );
       }
       for (   i = 0 ; i < vectTest.size(); i++ )   {
               vectTest[ i ].vPrint();
       }
       //     刪除全部m_strName = "3"的元素
       vectTest.erase( remove_if( vectTest.begin(), vectTest.end(), CStrFunc( "3" ) ),
               vectTest.end() );
       cout << "delete 3 after : " << endl;
       for (   i = 0 ; i < vectTest.size(); i++ )   {
               vectTest[ i ].vPrint();
       }
       //     刪除全部m_iPrice = 2的元素
       vectTest.erase( remove_if( vectTest.begin(), vectTest.end(), CIntFunc( 2 ) ),
               vectTest.end() );
       cout << "delete 2 after : " << endl;
       for (   i = 0 ; i < vectTest.size(); i++ )   {
               vectTest[ i ].vPrint();
       }
}
手工編寫for循環代碼刪除STL序列式容器中元素的方法,使用STL中通用算法或容器成員函數刪除元素的方法,二者之間的比較:
1.   前者代碼重複。
2.   前者容易出錯,不夠清晰。
3.   效率:
0                   1           2       3                 2           5       6                 7
0                   1           3       2                 5           6       7
0                   1           3       5                 6           7
用第一種方法刪除全部值爲2的元素
從上圖能夠看出,每刪除一個元素,後面的全部元素都到往前移動一位,致使一次內存大搬遷。

0                   1           2       3                 2           5       6                 7
0                   1           3       2                 5           6       6                 7
0                   1           3       5                 6           7

用第二種方法刪除全部值爲2的元素
從上面能夠看出,刪除時元素2被後面元素覆蓋,不會到元素移位和內存大搬遷,殘餘數據留到末尾一次所有刪除,也不會致使內存大搬遷,因此後者的方法要比前者在效率上好不少。 

3.list容器中刪除元素的方法
對於list容器,因爲list自己有remove和remove_if的成員函數,因此最好優先考慮list本身的算法,對於remove函數,比較簡單,再也不討論,對於remove_if函數,本人發如今vc6.0中有重大問題。我試了多種函數對象,老是編譯不過,經過查看源代碼,才發現VC6.0中對remove_if()函數做了簡化,只提供了一種比較函數,它只能刪除不等於某值的元素,VC6.0種remove_if()函數的源碼以下:(remove_if 以後容器大小並未改變)
typedef binder2nd<not_equal_to<_Ty> > _Pr1;
       void remove_if(_Pr1 _Pr)
               {iterator _L = end();
               for (iterator _F = begin(); _F != _L; )
                     if (_Pr(*_F))
                             erase(_F++);
                     else
                             ++_F; }
從源碼中能夠看出,remove_if中_Pr1函數對象被固定爲binder2nd<not_equal_to<_Ty> >一種格式。而在VC7.0中已經修改了這個bug,源碼以下:
template<class _Pr1>
               void remove_if(_Pr1 _Pred)
               {     // erase each element satisfying _Pr1
               iterator _Last = end();
               for (iterator _First = begin(); _First != _Last; )
                     if (_Pred(*_First))
                             erase(_First++);
                     else
                             ++_First;
               }
在VC7.0中remove_if()是成員模板函數,能夠用任何判斷條件的函數對象。
例如:
例 8:
#include <iostream>
#include <string>
#include <list>
#include <algorithm>
using namespace std;
class CTest{
public:
       CTest( int i ) : m_iPrice ( i ) {     }
       int operator == ( const CTest& right ) const{
               return ( m_iPrice == right.m_iPrice ) ? 1 : 0;
       }
       int operator != ( const CTest& right ) const{
               return ( m_iPrice != right.m_iPrice ) ? 1 : 0;
       }
       int operator < ( const CTest& right ) const {
               return ( m_iPrice < right.m_iPrice ) ? 1 : 0;
       }
private:
       int m_iPrice;
       friend class CTestFunc;
};
class CTestFunc {             //       函數對象
public:
       int m_value;
       CTestFunc( int i ) : m_value( i ) {}
       bool operator () ( const CTest& clFirst ) {
               return ( clFirst.m_iPrice == m_value ) ? true : false;     }
};
void main() {
       list< CTest > listTest;
       for ( int i = 0; i < 5; i++ ) {
               CTest clTest( i );
               listTest.push_back( clTest );
       }
       cout << "remove before : " << listTest.size() << endl;
//     刪除全部爲2的元素
       listTest.remove_if( CTestFunc( 2 )   ); //       這條語句在vc6.0中不能編譯經過,VC7.0中能夠
       cout << "remove after : 2, size =   " << listTest.size() << endl;

       //     刪除因此不等於2的元素,VC6.0中只能以這種方式調用remove_if()函數
       listTest.remove_if(   bind2nd( not_equal_to<CTest>(), 2 )     );
       cout << "remove after not equal to 2, size =   " << listTest.size() << endl;

       //     由於CTest類提供了==、< 成員函數,因此也能夠用remove函數
       listTest.remove( 2 ); //       刪除全部爲2的元素
       cout << "remove after : 2, size =   " << listTest.size() << endl;
}

不知道在VC6.0中可否突破只能函數對象被固定爲binder2nd<not_equal_to<_Ty> >一種格式的限制?歡迎諸位大蝦不吝賜教。不過採用通用算法remove_if只是多了幾回對象的賦值的負擔,若是對象不是太大,用通用算法的性能也是能夠接受的。

另外,這些天使用了VC7.0後,感受很是棒,不只幾乎符合Standard C++規範,錯誤提示也更清晰,而編譯速度和編譯後的文件大小大大減少,如我原來的一個大量使用了模板的程序,用VC6.0編譯後Release版的可執行文件大小爲1.2M,用VC7.0編譯後只有420K,我想可能VC7.0在代碼優化和模板代碼的膨脹等方面有了極大的改善;在STL的實現上也有了極大的改進,把原來的一些效率很差的地方都改進了,處理策略基本與SGI STL一致。

4.STL容器中元素爲指針狀況下的刪除方法
對於容器中的元素爲指針的刪除方法。若是容器中的元素爲指針則不能用上面介紹的用經過算法或成員函數的方法刪除元素,由於那樣作會致使內存泄露,容器中的元素爲指針指向的內存沒有釋放,在這種狀況下有如下方法解決:

1.   儘量不用指針做爲容器的元素。

2.   若是是由於要減小對象拷貝和賦值方面的負擔,而要在容器中存放指針的話,能夠考慮用boost庫中的智能指針shared_ptr包裝指針,達到容器中引用的語意。

3.   若是你不但願由於使用boost::shared_ptr增長引用計數的負擔,認爲引入智能指針很差理解,那麼你用指針做爲容器的元素要千萬當心,這時你要本身管理內存。

例如:    

例 9:用boost庫中的智能指針shared_ptr包裝指針的例子:
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
#include <algorithm>
#include <list>
#include <boost\smart_ptr.hpp> // 要包含BOOST類庫中智能指針的頭文件
using namespace std;
class CTest {
public:
       CTest( const string& str, int iPrice ) : m_strName( str ), m_iPrice( iPrice ) { }
       void vPrint() { cout << "name=" << m_strName << " price = " << m_iPrice << endl;
       }

private:
       string m_strName;
       int   m_iPrice;
       friend class CStrFunc;
       friend class CIntFunc;
};

//     函數對象,根據string比較
class CStrFunc {
       string m_str;

public:
       CStrFunc( const string& str ) : m_str( str ) {
       }
       //     此處要改成boost::shared_ptr<CTest>&,由於vector容器中的元素爲
//       boost::shared_ptr<CTest>
       bool operator() ( const boost::shared_ptr<CTest>& left ) {
               return ( m_str == (*left).m_strName ) ? true : false;
       }

};

//     函數對象,根據int比較
class CIntFunc {
       int m_iPrice;
public:
       CIntFunc( int iPrice ) : m_iPrice( iPrice ) {
       }
//     此處要改成boost::shared_ptr<CTest>&,由於vector容器中的元素爲
//       boost::shared_ptr<CTest>
       bool operator() ( const boost::shared_ptr<CTest>& left ) {
               return ( m_iPrice == (*left).m_iPrice ) ? true : false;
       }
};
void main( ) {

       vector< boost::shared_ptr<CTest>   > vectTest;
       int i;
       for (   i = 0; i < 5 ; i++ ) {
               stringstream stream;
               stream << i;
               string str = stream.str();
               boost::shared_ptr<CTest>   ptrShare( new CTest( str, i ) );
               vectTest.push_back( ptrShare );
       }
       for (   i = 0 ; i < vectTest.size(); i++ )   {
               ( *vectTest[ i ] ).vPrint();
       }
       //     刪除全部m_strName = "3"的元素
       vectTest.erase( remove_if( vectTest.begin(), vectTest.end(), CStrFunc( "3" ) ),
               vectTest.end() );
       cout << "delete 3 after : " << endl;
       for (   i = 0 ; i < vectTest.size(); i++ )   {
               ( *vectTest[ i ] ).vPrint();
       }
       //     刪除全部m_iPrice = 2的元素
       vectTest.erase( remove_if( vectTest.begin(), vectTest.end(), CIntFunc( 2 ) ),
               vectTest.end() );
       cout << "delete 2 after : " << endl;
       for (   i = 0 ; i < vectTest.size(); i++ )   {
               ( *vectTest[ i ] ).vPrint();
       }
}

以上代碼不會致使內存泄露。

例 10:本身編程刪除容器中元素爲指針的例子:

#include <iostream>
#include <sstream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
class CTest {
public:
       CTest( const string& str, int iPrice ) : m_strName( str ), m_iPrice( iPrice ) { }
       void vPrint() { cout << "name=" << m_strName << " price = " << m_iPrice << endl;
       }
private:
       string m_strName;
       int   m_iPrice;
       //     聲明友員函數,由於vDeleteVector函數要訪問CTest的private成員變量
       friend void vDeleteVector( vector< CTest*   >& vectTest, const string& str );
       friend void vDeleteVector( vector< CTest*   >& vectTest, int iPrice );
};
//     根據CTest類中m_strName比較
void vDeleteVector( vector< CTest*   >& vectTest, const string& str ) {
       vector< CTest* >::iterator itVect = vectTest.begin();
       for ( ; itVect != vectTest.end();; ) {
               if ( (*itVect)->m_strName == str ) {
                     //       刪除vector容器中指針元素指向的內容,防止內存泄露
                     delete *itVect;
                     itVect = vectTest.erase( itVect );
               }
               else {
                     ++itVect;
               }
       }
}
//     根據CTest類中m_iPrice比較
void vDeleteVector( vector< CTest*   >& vectTest, int iPrice ) {
       vector< CTest* >::iterator itVect = vectTest.begin();
       for ( ; itVect != vectTest.end(); ) {
               if ( (*itVect)->m_iPrice == iPrice ) {
                     //       刪除vector容器中指針元素指向的內容,防止內存泄露
                     delete *itVect;
                     itVect = vectTest.erase( itVect );
               }
               else {
                     ++itVect;
               }
       }
}

void main( ) {
       vector< CTest*   > vectTest;
       int i;
       for (   i = 0; i < 5 ; i++ ) {
               stringstream stream;
               stream << i;
               string str = stream.str();
               CTest* pclTest =   new CTest( str, i ) ;
               vectTest.push_back( pclTest );
       }
       for (   i = 0 ; i < vectTest.size(); i++ )   {
               vectTest[ i ]->vPrint();
       }
       //     刪除全部m_strName = "5"的元素
       vDeleteVector( vectTest, "3" );
       cout << "delete 3 after : " << endl;
       for (   i = 0 ; i < vectTest.size(); i++ )   {
               vectTest[ i ]->vPrint();
       }
       //     刪除全部m_iPrice = 2的元素
       vDeleteVector( vectTest, 2 );
       cout << "delete 2 after : " << endl;
       for (   i = 0 ; i < vectTest.size(); i++ )   {
               vectTest[ i ]->vPrint();
       }
} dom

相關文章
相關標籤/搜索