标准::设置<string>和内存

std::set<string> and memory

本文关键字:内存 gt lt 设置 标准 string      更新时间:2023-10-16

我使用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在哪里?

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

为什么是3mb ?

很抱歉我的英语不好,提前谢谢你

集合大小和其他内存使用已经在评论中回答了。

vector使用的内存小于4.1MB,因为visual studio的std::string将小字符串存储在字符串内部的缓冲区中。如果字符串比缓冲区大,那么它将分配一个动态缓冲区来存储字符串。这意味着str.capacity() + sizeof(string)对于小于该缓冲区大小的值是不正确的(在您的情况下,visualc的缓冲区恰好是16字节)。

尝试在字符串中使用更大的值运行它。例如,在将其放入矢量之前,将常量字符串"12345678901234567890"添加到每个值,您的内存使用应该增加超过200k(20*10,000)的额外数据,因为字符串将不得不开始分配动态缓冲区。

当你把项目放入一个集合时,不仅项目本身会占用空间,而且还会设置内部记账。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字节。