2011-01-11 101 views
5

我能想到的填充std::vector在填充載體

假設的三種不同的方式,我們有

vector<int> v(100, 0); 

然後,我希望它保持(1,1,1)。我們可以這樣做:

v.clear(); 
v.resize(3, 1); 

或者

v = vector<int>(3, 1); 

而且我知道另一種方法:

vector<int>(3, 1).swap(v); 

首先的問題是:任何人的最好的方法?

第二個問題:假設v被聲明在主函數之外。根據這answer,內存將被分配在數據段中。如果我使用第二種或第三種方法,內存是否會分配到堆棧上?

+4

這是不正確的。無論在哪裏聲明,原始數組都會分配它們的內存。 `vector`將始終堆分配。 int []!=向量。 – Puppy 2011-01-11 19:30:39

回答

3

所以,這裏的差異,我會讓你決定什麼是最適合你的情況。

v.clear(); 
v.resize(3, 1); 

在這種情況下,我們已經將矢量標記爲清除。爲了容納100個元素(它可以超過100個元素所需的空間),它仍然擁有它分配的任何東西。然後我們添加了3個值爲1的項目。所有這些都是增加大小計數器並重置3個值,底層內存仍然是相同的大小。

v = vector<int>(3, 1); 

這確實非常不同之處在於創建的臨時額外的載體,同樣的事情,而不是有被間歇性的地方計數器爲0,然後用一些值3,簡單複製計數器大小,然後再執行一個類似於memcpy的操作來複制3個元素。爲v分配的底層內存大小仍足以容納100個整數。

vector<int>(3, 1).swap(v); 

這一個是顯着不同的。在這種情況下,我們創建一個臨時向量,它包含3個元素,它們都被初始化爲1.理論上,它仍然可以爲100個元素保留足夠的內存,但機會很少。然後我們將這個向量與我們自己的交換,讓臨時被破壞。這有額外的好處,清除我們的舊矢量分配的任何額外內存不在臨時。這樣做的方式是兩個向量(我們的v和臨時的)交換的不僅僅是計數器和值,它們還交換緩衝區指針。

這是收縮矢量的唯一方法。

2

要首先回答第二個問題:vector將始終爲其包含的對象動態分配內存,因此它將最終堆在堆上。

至於哪種重新分配方法更好,我會說你的第一或第二種方法使你的意圖最清楚,這是最重要的屬性。

9

您如何使用該任務的矢量成員?

std::vector<int> v(100); 
v.assign(3, 1); // this is what you should do. 
+0

忽略這些顯而易見的事情是多麼容易。 – 2011-01-11 19:41:24

+1

它是v.clear()的縮寫版本; v.resize(3,1);`具有相同的異常安全問題。 – 2011-01-11 20:05:21

1

交換將有效地將矢量縮小爲3個元素。其他人可能不會。

vector<int> v(100); 
v.assign(3, 1); 
assert(v.size() == 3); 
assert(v.capacity() != 3); 

v = vector<int>(3, 1); 
// Now, v.capacity() is likely not to be 3. 

vector<int>(3, 1).swap(v); 
assert(v.capacity() == 3); 

其他方法不會在內部調整矢量大小。即使size()成員返回3,它仍將在內存中佔用100 * sizeof(int)個字節。嘗試顯示v.capacity()以說服自己。

+0

差不多。我們不知道這些情況下所佔用的尺寸究竟是多少。許多向量實現預留額外的空間,以便頻繁插入不會單獨導致重新分配和移動。 – 2011-01-11 19:47:16

1

在前面的文章中沒有提到的一個問題在選擇這些替代方案時非常重要。即異常安全。 vector<int>(3, 1).swap(v);有很強的例外安全保證。表格v = vector<int>(3, 1);也可以提供這種保證,如果分配實施交換。第一個選擇是不安全的:v.clear(); v.resize(3, 1);