std :: set <string>和memory </string>

时间:2014-05-14 07:04:51

标签: c++ std

我使用Ms Visual Studio2010 Express并拥有下一个代码

set<string> res;
for(uint x = 0; x<100000;++x) res.insert( vtos(x,0) );
uint size1=0;uint size2=0;uint size3=0;
set<string>::const_iterator it=res.begin();
for(;it!=res.end();++it){
    string str = *it;
    size1+=str.size();
    size2+=str.capacity();
    size3+=str.capacity() + sizeof(string);
}
cout << "size1 == " << ((float)size1)/1024/1024 << endl;
cout << "size2 == " << ((float)size2)/1024/1024 << endl;
cout << "size3 == " << ((float)size3)/1024/1024 << endl;
while(true){}

输出是

size1 == 0.466242
size2 == 1.43051
size3 == 4.1008

循环(最后,它是坏事,我知道)仅用于观看TaskManager。 在TaskManager中,我看到我的应用程序的内存是6,11 Mb

为什么是6M? ~2Mb在哪里?

如果我用vector替换set(调整大小为100000),则输出将是相同的,但在任务管理器中我看到~3,400Mb。

为什么是3 Mb?

抱歉我的英语不好,请提前告知你。

2 个答案:

答案 0 :(得分:1)

评论中已回答了设置大小和其他内存使用情况。

矢量使用的计算量小于4.1MB,因为visual studio的std :: string会将小字符串存储在字符串内部的缓冲区中。如果字符串大于缓冲区,则它将分配动态缓冲区来存储字符串。 这意味着str.capacity() + sizeof(string)对于小于缓冲区大小的值(在您的情况下是所有字符串,因为Visual C&C的缓冲区恰好是16个字节)不正确。

尝试在字符串中使用更大的值运行它。例如添加常量字符串&#34; 12345678901234567890&#34;将每个值放到向量之前,你的内存使用量应该超过200k(20 * 10,000)的额外数据,因为字符串必须开始分配动态缓冲区。

答案 1 :(得分:0)

当您将项目放入集合时,不仅项目本身会占用空间,还会设置内部簿记。 std :: set通常实现为红黑树,这意味着集合中的每个项目都有一个节点。在MSVC上,节点如下所示:

template<class _Value_type,
class _Voidptr>
struct _Tree_node
{   // tree node
    _Voidptr _Left; // left subtree, or smallest element if head
    _Voidptr _Parent;   // parent, or root of tree if head
    _Voidptr _Right;    // right subtree, or largest element if head
    char _Color;    // _Red or _Black, _Black if head
    char _Isnil;    // true only if head (also nil) node
    _Value_type _Myval; // the stored value, unused if head

private:
    _Tree_node& operator=(const _Tree_node&);
};

如您所见,value只是节点的一部分。在我的PC上,sizeof(string)在编译为32位可执行文件时为28个字节,树节点的大小为44个字节。