1. 程式人生 > >Effective_STL 學習筆記(十四) 使用 reserve 來避免沒必要的重新分配

Effective_STL 學習筆記(十四) 使用 reserve 來避免沒必要的重新分配

 

對於vector和string,當需要更多的空間,以realloc等價的思想來增長。類似於realloc的操作有四個部分:

  1. 分配新的記憶體塊,它有容器目前容量的幾倍。大部分實現中,vector和string的容量以2為因數增長。

   也就是說,當容器必須擴充套件時,它的容量每次翻倍。

  2. 把所有元素從容器的舊記憶體拷貝到它的新記憶體。

  3. 銷燬舊記憶體中的物件。

  4. 回收舊記憶體。

這些步驟都是很昂貴的,而且所有指向 vector 和 string 中的迭代器、指標和引用都會失效。

 

在標準容器中,只有 vector 和 string 提供了所有這四個相關的成員函式:

  1. size() 告訴你容器中多少個元素;

  2. capacity() 告訴你容器在它已經分配的記憶體中可以容納多少元素;

  3. resize( Container::size_type n ) 強制把容器改為容納 n 個元素。

  4. reserve( Container::size_type n ) 強制容器把它的容量改為至少 n,提供 n 不小於當前大小 

以上,只要有元素插入而且容器的容量不足時就會發生重新分配(包括它們維護的原始記憶體分配和回收,物件的拷貝和析構和迭代器、指標和引用的失效)。所以避免重新分配的關鍵是使用 reserve 儘快把容器的內容設定為足夠大,最好在容器被構造之後立刻進行。

1   vector<int> v;
2   v.reserve(1000);
3   for( int i = 1; i <= 1000; i++ )
4     v.push_back(i);

這樣迴圈中不會重新分配。

 

在大小和容量的關係讓我們可以預言什麼時候插入將引起 vector 或 string 執行重新分配

1   string s;
2   . . .
3   if( s.size() < s.capacity() )
4     s.push_back( 'x' );

 

回顧本條款的主旨,通常兩種情況使用 reserve 來避免不必要的重新分配:

  1. 確切或者大約知道有多少元素最後出現在容器中。

  2. 保留可能需要的最大空間,然後,新增資料完成,修掉多餘的容量