C++ STL容器的内存消耗

C++ STL容器的内存消耗,c++,memory-management,stl,map,vector,C++,Memory Management,Stl,Map,Vector,我正在开发一个应用程序,其中我计划使用两个STL容器。如果内存消耗达到阈值,应用程序将采取某些步骤。为此,我需要对STL容器使用的内存量进行近乎精确的计算 vector<string> StringList map<string, int> mapstring 然后最后添加到这个sizeof(StringList) 对于mapstring的大小,在容器的所有键上循环并不断添加字符串大小,然后添加int的大小,即mapstring.size()*sizeof(int)。然

我正在开发一个应用程序,其中我计划使用两个STL容器。如果内存消耗达到阈值,应用程序将采取某些步骤。为此,我需要对STL容器使用的内存量进行近乎精确的计算

vector<string> StringList
map<string, int> mapstring
然后最后添加到这个
sizeof(StringList)

对于mapstring的大小,在容器的所有键上循环并不断添加字符串大小,然后添加int的大小,即
mapstring.size()*sizeof(int)
。然后最后添加到这个
sizeof(mapstring)


我想更好的方法是指定自己的分配器类,并跟踪其中的内存使用情况,但编写一个分配器类并不是件容易的事。这个估计看起来不错吗?

一个
std::vector
通常总共占用3个机器字+sizeof(element)*
容量()
。对于典型的实现,开销包括指向向量的开始、结束和当前大小的指针。元素本身存储在连续内存中
capacity()
通常可以容纳两倍于实际数量的元素

一个
std::map
通常每个元素总共需要大约2个机器字,+3个机器字+[sizeof(element)+sizeof(int)]*num\u内存元素。对于典型的实现,开销包括指向存储元素的指针。元素本身存储在二叉树中,带有指向其父元素和两个子元素的指针


有了这些经验法则,您只需要知道每个字符串的平均字符数和总内存消耗量的字符串总数。

对于
std::vector
std::string
,容量比大小更重要 这是一个更好的近似值。对于基于节点的容器(
std::set
, 等等),您需要将节点数乘以(大致等于 元素)乘以每个节点的大小。然而,只有在以下情况下,这才是准确的 分配器不对节点使用优化池分配器

但是,如果您确实想知道使用了多少内存,请 更好的策略是更换新的全球
运营商
操作员删除
,并跟踪实际分配情况。甚至更多 准确的做法是替换
malloc
free
。从形式上讲,这不是 允许,但在实践中,我从未遇到过 它不起作用。另一方面,如果更换
malloc
free
, 您必须自己实现实际的内存管理。如果你 替换
操作员新建
操作员删除
,您可以使用
malloc
免费的
,这使得它相当简单

还要注意,每个分配都有一些固定的开销。十万美元 每个10字节的分配将比
10个分配,每个分配100000字节。

类似的问题:这是获得大致下限的合理方法,但开销可能比您想象的要大得多。例如,一个
std::map
元素必须包含各种额外的指针,以及与保持其平衡相关的信息。。。Valgrind工具massif跟踪堆分配,可能对分析程序内存使用情况有所帮助。这还取决于您使用的STL实现。e、 g.STLPort或gcc STL“我想更好的方法是指定自己的分配器类并跟踪其中的内存使用情况,但编写一个分配器类可能并不简单。”——这确实是最好的方法,比事后猜测STL实现要好得多。你不能只问操作系统进程使用了多少内存吗?通常应用程序不会消耗它使用的任何内存。对于
std::vector
,你应该使用
容量,而不是元素数。如果
std::map
使用了一个池分配器(还有很多),那么它很可能会分配比
map
@JamesKanze Tnx中的元素多得多的节点,更新为capacity()备注。那么对于
std::map
,是否有一种非侵入性的方式(即不记录分配器)来获取内存消耗?如果您不知道实现,则没有办法;如果分配器使用一个节点池,则可能没有方法,即period。这里最简单的解决方案就是将全局
运算符new
运算符delete
替换为跟踪分配的运算符。(默认分配器需要使用
::operator new
来获取它们分配的内存。)此外,您关于
容量()
的注释最多可以容纳两倍于实际元素数的空间是不正确的。容量没有任何限制,只不过它会成倍增长。典型的倍数是1.5和2,但肯定允许更大(或更小)。@JamesKanze我反复提到“典型实现”,因为没有强制实现。替换新的将给我在堆分配期间使用的内存。对于这种用法,我必须增加所有容器的开销,即sizeof(vector)+sizeof(string)等,这取决于您试图测量的内容。替换新的命令将使您在C++中使用动态内存(但不在任何可能使用的C部分)。这就是我所理解的“内存消耗”。它不会计算堆栈上局部变量
std::vector
中的三个指针,但会计算该向量中所有字符串使用的所有内存(因为向量内容的所有内存都是动态分配的)。
string size = sizeof(string) + string.capacity()*sizeof(char)