11

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

vector<string> StringList
map<string, int> mapstring

这就是我估计内存的方式:

对于 的大小StringList,循环遍历向量的所有元素并继续添加字符串大小。

string size = sizeof(string) + string.capacity()*sizeof(char)

然后最后添加到这个sizeof(StringList);

对于 mapstring 的大小,循环遍历容器的所有键并继续添加字符串大小,然后添加 int 的大小,即mapstring.size()*sizeof(int). 然后最后添加到这个sizeof(mapstring);

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

4

2 回答 2

11

Astd::vector<element>通常总共需要 3 个机器字+ sizeof(element) *capacity()内存。对于典型的实现,开销包括指向向量开始、结束和当前大小的指针。元素本身存储在连续的内存中。capacity()通常有最多两倍于实际元素数量的空间。

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

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

于 2012-08-07T07:50:43.460 回答
11

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

但是,如果您真的想知道正在使用多少内存,更好的策略是替换全局operator newand operator delete并跟踪实际分配。更准确的方法是替换mallocfree。形式上,这是不允许的,但在实践中,我从未遇到过它不起作用的实现。另一方面,如果替换mallocand free,则必须自己实现实际的内存管理。如果你替换operator newand operator delete,你可以使用mallocand free,这使得它相当简单。

还要注意,每个分配都有一些固定的开销。与 10 次每次 100000 字节的分配相比,每次 10 字节的 100000 次分配会消耗更多的内存。

于 2012-08-07T08:02:09.193 回答