使用reserve要再次避免不必要的分配

2021-09-07 01:48:23 字數 1442 閱讀 4702



關於stl容器,最了不起的一點是,它們會自己主動增長以便容納下你放入當中的資料,僅僅要沒有超出它們的最大限制就能夠。對於vector和string,增長過程是這樣來實現的:每當須要很多其它空間時,就呼叫與realloc類似的操作。

這一類似於realloc的操作分為4部分:

分配一塊大小為當前容量的某個倍數的新記憶體。

在大多數實現中,vector和string的容量每次以2的倍數增長,即,每當容器須要擴張時,它們的容量即加倍。

把容器的全部元素從舊的記憶體複製到新的記憶體中。

析構掉舊記憶體中的物件。

釋放舊記憶體。

reserve成員函式能使你把又一次分配的次數降低到最低限度,從而避免了又一次分配記憶體和指標/迭代器/引用失效帶來的開銷。在解釋reserve如何做到這一點之前。我將簡單概括一下4個相互關聯,但有時會被混淆的成員函式。在標準容器中,僅僅有vector和string提供了全部這4個函式:

size()

說明了改容器中有多少個元素。它不會告訴你該容器為自己所包括的元素分配了多少記憶體。

capacity()

說明了改容器利用已經分配的記憶體能夠容納多少個元素。

這是容器所能容納的元素總數。而不是它還能容納多少個元素。

假設你想知道乙個vector由多少為被使用的記憶體,你就得從capacity()中減去size()。假設size和capacity返回相同的值。就說明容器中不再有剩餘空間了。

resize(container::size_type n)

強迫容器改變到包括n個元素的狀態。

在呼叫resize之後,size將返回n。

假設n比當前的大小要小,則容器尾部的元素將會被析構掉。假設n比當前的大小要大。則通過預設建構函式建立的新元素將被加入到容器的末尾。假設n比當前的容量要大,那麼在加入元素之前,將先又一次分配記憶體。

reserve(container::size_type n)

強迫容器把它的容量變為至少是n。前提是n不小於當前的大小。這一般會導致又一次分配,由於容量會新增。(假設n比當前的容量小,則vector忽略該呼叫。什麼也不做;而string則可能把自己的容量減為size()和n中的最大值,可是string的大小肯定保持不變。)

比如:假定想建立乙個包括1到1000之間的值的vector。

假設不使用reserve。你可能會這樣做:

vectorv;

for (int i = 1;i <= 1000;++i)

v.push_back(i);

該迴圈在進行過程中將導致2到10次又一次分配。假設使用reserve,例如以下所看到的:

vectorv;

v.reserve(1000);

for (int i = 1;i <= 1000;++i)

v.push_back(i);

則在迴圈過程中將不會再發生又一次分配。

假設想除去多餘的容量。請參閱怎樣有效除去多餘的容量

避免不必要的float

float中文翻譯為浮動,很形象的翻譯,在css很常用,當你需要吧兩個塊級元素定排放在同一高度上經常會用到float,先看一下float的 屬性。先看一下float可能的值 float left 元素向左浮動 float right 元素向右浮動 float none 不浮動 float inher...

避免不必要的物件

一般來說,最好能重用物件而不是在每次需要的時候就建立乙個相同功能的新物件。重用方式既快速,又流行。如果物件是不可變的,它就始終可以被重用。最為乙個極端的反面例子,考慮下面的語句 string s new string string don t do this 該語句每次被執行的時候都建立乙個新的st...

避免建立不必要的物件

下面是乙個比較微妙也比較常見的反面的例子,其中涉及可變的date物件,他們的值一旦計算出來之後就不再變化。這個類建立了乙個模型 其中有乙個人,並有乙個isbabyboomer方法,用來檢驗這個人是否為乙個babyboomer,換句話說,就是檢驗這個人是否出生於1946年至1964年之間。public...