2011-09-23 31 views
3

我正在C++中進行練習,但即時獲得意想不到的輸出,我希望有人能解釋。練習題要求我創建一個名爲rock的類,該類有一個默認的構造函數,一個拷貝構造函數和一個析構函數,所有這些都會向cout宣佈自己。在C++中的矢量內部工作?

在我嘗試採用值添加這個類的成員的向量的主要方法:

vector<Rock> byValue; 
Rock r1, r2, r3; 
byValue.push_back(r1); 
byValue.push_back(r2); 
byValue.push_back(r3); 
cout << "byValue populated\n\n"; 

我預期的(和在鍛鍊方案示出)的輸出是:

Rock() 
Rock() 
Rock() 
Rock(const Rock&) 
Rock(const Rock&) 
Rock(const Rock&) 
byValue populated 

~Rock() 
~Rock() 
~Rock() 
~Rock() 
~Rock() 
~Rock() 

但是輸出我得到的是:

Rock() 
Rock() 
Rock() 
Rock(const Rock&) 
Rock(const Rock&) 
Rock(const Rock&) 
~Rock() 
Rock(const Rock&) 
Rock(const Rock&) 
Rock(const Rock&) 
~Rock() 
~Rock() 
byValue populated 

~Rock() 
~Rock() 
~Rock() 
~Rock() 
~Rock() 
~Rock() 

任何人都可以解釋爲什麼似乎是共同額外要求py的構造函數和析構函數?

回答

8

當矢量調整大小時,元素必須移動到新的位置。

這是正常的。

如果你打電話

byValue.reserve(10); 
push_back任何呼叫前

,額外的副本應該消失。

4

一個向量連續存儲它的元素。爲了避免每次插入元素時總是重新分配內存,它會分配一堆內存。這就是爲什麼矢量有兩個關於「大小」的方法:size()它告訴存儲的元素的數量,capacity()它表示分配的內存量。

通常(但這取決於STL的實施),它的先例容量增加了一倍。當它分配更多的內存,並且由於數據必須連續存儲(與list相比),它必須移動其內部數據;和STL複製數據,這就是爲什麼你有這麼多的調用構造/析構函數。

如果知道向量中將存儲多少個元素,則可以使用reserve來指示首先應該分配多少內存。

1

std::vector具有有限數量的內存來存儲元素。你可以用capacity查詢多少。您還可以通過reserve方法告訴向量來獲取額外的內存。

當你將一個元素推到vector上並且它的容量爲零時(它已經用完了所有額外的內存),它會分配一個新的更大的數組並複製原始元素。這是所有額外副本都來自的地方。

看着你的輸出,它看起來像向量必須增長兩倍。如果在推動任何東西之前更改了代碼以調用預留,矢量永遠不需要增長,並且不會有額外的副本。

下面是一個詳細的代碼片段,它顯示了所有這些如何結合在一起:ideone.com