最近幾天重溫了《STL源碼剖析》這部著作,對一些知識點做個記錄。
vector的技術實現,關鍵在於其對大小的控制以及重新配置時的數據移動效率。一旦vector舊有空間滿載,如果客戶端每新增一個元素,vector內部只是擴充一個元素的空間,實爲不智,因爲所謂擴大空間(不論多大),一如稍早所說,是“配置新空間/數據移動/釋放舊空間”的大工程,時間成本很高,應該加入某種未雨綢繆的考慮。
所謂動態增加大小,並不是在原空間之後接續新空間(因爲無法保證原空間之後上油可供配置的空間),而是以原大小的兩倍另外配置一塊較大空間,然後將原內容拷貝過來,然後纔開始在原內容之後構造新元素,並釋放原空間。因此,對vector的任何操作,一旦引起空間重新配置,指向原vector的所有迭代器舊都失效了。(摘自《STL源碼剖析》)
先來看下vector是如何拓展空間的
int main()
{
std::vector<int> vec;
int lastCapacity = 0;
for (size_t i = 0; i < 100; i++)
{
vec.push_back(i);
if (lastCapacity!= vec.capacity())
{
lastCapacity = vec.capacity();
std::cout << i << "->" << lastCapacity << "->" << &vec[0] << "\n";
}
}
getchar();
}
運行結果:
可以看到新增一個元素沒有剩餘空間時,就會擴展新的空間(新增加的空間約爲0.5倍的舊空間),並把內容移動到新的地址。
由於需要不斷移動數據,因此頻繁新增元素(不斷開闢新空間/移動數據)會帶來額外的時間開銷。
簡單測試下效率影響:
測試結果:
通過測試結果看,頻繁新增元素帶來的時間開銷還是比較大的,這還是數據比較少的情況,數據越多效率影響會越大。