2014-01-14 44 views
0

EDITED 該代碼在VS2010中以Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86編譯爲32位,並在Win7 64位機器上運行。爲什麼插入空結構保留向量增加內存?

程序爲空main機身需要1KB的內存。

The sizeof(Bag)=32。 (=短字符串的內部緩衝區爲16字節+如果字符串大於16字節則加4字節指向內存+字符串的其他內容)。

保留200,000個元素後,矢量v需要6400KB的內存。因此,直到現在的總內存是7400KB。

我不明白的是,在插入100,000個元素(小於預留容量v)到v後,內存使用量增加到14,800KB。如果我和int替換string這樣的總使用存儲器將是因爲它應該是1,800KB(= 1000KB + 200 * 4B)

1. struct Bag 
2. { 
3.  string s;  
4. }; 

5. vector<Bag> v; 
6. v.reserve(200000); 

7. for(int i = 0; i < 100000; ++i) 
8. { 
9.  v.push_back(Bag()); 
10. } 
+0

你是如何驗證內存使用情況? – Chad

+0

使用'任務管理器'。我知道這可能不是最準確的工具,但它在各種機器上顯示非常確定性的內存行爲(當然具有相同的架構)。 – theateist

+0

您是否正在運行完全優化,因此不會生成不必要的副本?你可以嘗試用一個'resize(100000)'替換'push_back()'調用嗎? – Chad

回答

2

std::string包含一個額外的所分配的存儲器元件以包含字符串的內容;實際的絃樂對象本身只是故事的一半。一些實現有一個優化來消除非常短的字符串的額外開銷,但這不能保證。

每個分配使用的內存量將取決於您的平臺的最小分配特性。

+0

這就是爲什麼sizeof(Bag)= 32。(= 16字節的內部緩衝區字符串+其他16個指針和其他東西)。所以,當我保留200,000的32字節,然後增加10萬'袋'沒有分配字符串應該發生,因爲空字符串將存儲在內部緩衝區。因此,添加'Bag'時分配什麼被添加到矢量? – theateist

+0

@theateist我不能說沒有看在你使用的'std :: string'的特定實現中,你甚至沒有提到你有哪個編譯器。 –

+0

我更新了我的帖子。編譯器是Microsoft®(R)32位C/C++優化編譯器版本16.00.40219.01,用於80x86' – theateist

0

reserve()函數爲Bag對象包分配內存。這塊內存包含std::string所有數據成員的空間。 std::string分配內存用於保存字符串數據並將指針指向數據成員。 std::string數據的內存塊是您觀察到的附加空間。 如果是int數據成員:它沒有額外的緩衝區,所以沒有額外的內存分配。

下面的代碼片段顯示,字符串有額外的字節分配:

#include <string> 
#include <iostream> 

int main() { 
     std::string s; 
     std::cout << "[1] Buf: " << s.capacity() << std::endl; 
     s = "Now it's contain some data"; 
     std::cout << "[2] Buf: " << s.capacity() << std::endl; 
     return 0; 
} 

輸出如下:

./a.out 
[1] Buf: 22 
[2] Buf: 47 
+0

請參閱我對@Mark的評論。該字符串有16個字節的內部存儲器。當將'Bag'添加到矢量 – theateist

+0

@theateist時,沒有分配請參閱添加的代碼片段 – vershov

+0

我知道它會增長,因爲新字符串的長度是26個字節,這是**更大**然後是內部緩衝區的長度字符串(在我的情況下是16),這就是爲什麼它在堆中分配空間。但是,我將**空**字符串插入長度小於**的向量中,所以它不應該分配任何東西! – theateist

相關問題