2014-01-14 42 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

相关问题