容器內存釋放問題(STL新手筆記)


  最近看了下STL,用的過程中有一些體會需要記一下。

  容器的空間申請和基本函數操作,以及algorithm等都比較好理解,用起來也很方便,比較關鍵的是容器元素包含指針時,空間的申請和釋放問題,這個覺得STL做得挺亂的。總結了幾點注意的。

 

  1)自己new的空間,在釋放的時候必須先delete,然后再釋放容器。例如list<char*> MS,鏈表中存的是自己的動態字符串,如果字符串是自己動態申請的,則在釋放該鏈表的時候,需要先delete [](*curIter),然后再MS.erase(curIter),其中curIter是當前迭代器。

 

  2)list的成員函數erase、remove和clear都會自動調用元素各自的析構函數,所以如果元素是自己定義的類,並且有完善的析構函數,則直接刪除即可。這類鏈式存儲,一個元素一個元素遞增空間的結構,這些函數可以真正地改變list占用的內存大小。

 

  3)vector等的空間釋放方式。需要注意兩點:

  A、理解erase-remove慣用法,包括erase和remove函數的返回值等,http://blog.csdn.net/peteryxk/article/details/1804696這篇文章中講的比較清楚,下面是一個代碼示例:

View Code
 1 /*刪除vector對象vec中等於10的元素,第一種方法*/
 2 for ( begin = vec.begin() ; begin != vec.end() ; /* ++begin */ )
 3 {
 4 if ( 10 == *begin )
 5         {
 6                 begin = vec.erase( begin ) ;
 7         }
 8         else
 9         {
10                 ++begin ;
11         }
12 }
13 /*remove-erase方法*/
14 vec.erase(remove (vec.begin() ,vec.end(),10) , vec.end()) ;

需要搞明白remove和erase在這種順序結構中的工作原理。

  B、由於vector的空間是階梯遞增式管理的,而且基本只增不減,也就是,雖然調用remove、erase或者clear等方法(他們會調用所存元素對象的析構函數,如果元素是用戶定義的類,並且有完善析構函數釋放掉該類的對象動態申請的空間,則remove和erase確實會釋放掉一些內存,但是容器本身的空間還是難以被利用),容器之前分配的空間仍不會被回收,大小不變,仍舊不能被其他程序使用,這是由STL的內存管理機制決定的,目的是為了提高效率。那么應該怎么回收vector的內存呢?這里就用了一個小的技巧,swap方法,代碼如下:

View Code
 { 
     std::vector<int> tmp;   
     vec.swap(tmp); 
  }//使用一個局部變量空的容器temp,與vec交換,退出temp作用域后,temp會釋放自己的空間,而此時vec已經是空的容器    

list由於是鏈式存儲的,跟vector機制不一樣,他的成員函數remove、erase、pop_front、pop_back和clear等都會回收被刪除元素的內存空間,不需要swap協助。

  對於vector,作如下實驗就可以看到,它的空間其實一直還是保留着的,除非swap掉:

View Code
 1     vector<int> vec;
 2 
 3     for(int i=1;i<=10;i++)
 4     {
 5         vec.push_back(i);
 6         cout<<vec.size()<<"  "<<vec.capacity()<<"  "<<vec.max_size()<<endl;
 7     }
 8     cout<<endl;
 9     for(int i=1;i<=10;i++)
10     {
11         vec.erase(remove(vec.begin(),vec.end(),i),vec.end());
12         cout<<vec.size()<<"  "<<vec.capacity()<<endl;
13     }
14     cout<<endl;
15     if(true)
16     {
17         vector<int> temp;
18         vec.swap(temp);
19     }
20     cout<<vec.size()<<"  "<<vec.capacity()<<endl;

  運行結果如下:


  4)下面給出erase(刪除迭代器區間的內容)和remove函數(一般用來刪除容器中等於特定值的內容)的返回值定義,以方便理解3)A.

  List::erase() Return value:

A bidirectional iterator pointing to the new location of the element that followed the last element erased by the function call, which is the list end if the operation erased the last element in the sequence.

  List::remove() Return value: None

  Vector::erase() Return value:

A random access iterator pointing to the new location of the element that followed the last element erased by the function call, which is the vector end if the operation erased the last element in the sequence.

  非成員函數,算法庫中的remove() Return value:

A forward iterator pointing to the new end of the range that includes all the elements with a value that does not compare equal to value.

 

  5)關於STL的內存管理,有一篇文章http://philoscience.iteye.com/blog/1456509中好像說得挺清楚的,有空再看看。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM