了解内存分配

时间:2016-03-03 20:54:20

标签: c++ memory-management heap-memory

我试图理解std::list数据结构如何分配内存。我做了一个小测试程序

#include <cstdio>
#include <vector>
#include <iostream>
#include <string>
#include <list>

class MyClass
{
public:

 MyClass();
~MyClass(){}

private:
std::list<unsigned char> numlist;
};

MyClass::MyClass()
{
numlist.push_back(1);
}

int main()
{ 

 MyClass c; // instantiate
}

我在valgrind

中运行了上面的代码片段
$valgrind --leak-check=full ./indepth 
==32330== HEAP SUMMARY:
==32330==     in use at exit: 0 bytes in 0 blocks
==32330==   total heap usage: 1 allocs, 1 frees, 24 bytes allocated

请帮助我理解为什么在这里分配了24个字节。

4 个答案:

答案 0 :(得分:2)

在不了解特定编译器及其选项的情况下,很难给出明确的答案。但是对push_back的调用将为它创建的列表元素分配一个节点,该节点将有两个指针(一个用于下一个节点,一个用于前一个节点),一个int包含储存的价值。要获取有关这些部件尺寸的详细信息,请运行以下程序:

#include <iostream>

int main() {
    std::cout << sizeof(int*) << ", " << sizeof(unsigned char) << '\n';
    return 0;
}

这将告诉你指针有多大以及int有多大。

答案 1 :(得分:2)

std::list中每个元素的确切大小取决于STL实现,但通常它实现为双链表,这意味着每个节点(代表元素)需要至少3个数据成员(上一个节点下一个节点,以实现双链接列表数据)。

在gcc实现中,文件 std_list.h _List_node包含此节点的定义。 2个指针(32位中的2 * 4个字节或64位中的2 * 8个字节)加上sizeof(数据)。

除此之外,列表可能必须维护一些其他内部信息,例如大小(因为C ++ 11是由std::list::size() O(1)的标准规定的

注意:

STL实施 = 标准库实现(编译器附带的C ++标准库的实现或配置为由编译器使用)

  • gcc 的情况下 libstdc ++
  • 如果 clang 可以是 libc ++ (clang实现)或 libstdc ++ (gcc实现)
  • 如果是 VC ++ ,则其内部实施(通过 Dinkumware )。

还有其他STL实现,如 STLPort 等......这些细节与实现有关。唯一可以确定的方法是查看特定版本STL实现的代码,确切的大小可能随时改变。

答案 2 :(得分:1)

  

请帮助我理解为什么在这里分配了24个字节。

此类详细信息是特定于实现的,因此最终答案取决于编译器和标准库的源代码或文档。在另一个实现中,内存使用可能会有很大不同。

但是,可以基于双重链表的简单实现进行有根据的猜测:在编译时通常无法知道节点数,因此它们可能需要动态分配。节点应具有指向下一个和上一个节点的指针以及存储的数据。这是1 string text = " "; int StartLocation = 0; int EndLocation = 0; //I roughly know the starting location //starting at I=2248 so I don't //through entire document for (int i = 2248; i < 2700; i++) { text = document.Paragraphs[i + 1].Range.Text.ToString(); if (text.Contains("firstWordImSearchingFor")) { StartLocation = i; } if (text.Contains("lastWordImSearchingFor")) { EndLocation = i; } } //delete everything between those paragraph locations //(not working correctly/ skips lines) for(int i = StartLocation; i<EndLocation-1i++) { document.Paragraphs[i+1].Range.Delete(); } 和2指针。在特定的体系结构中,很可能指针的大小恰好是8个字节。 int通常也适合8个字节,但即使它更小,也必须将节点填充到最接近的8字节边界以满足指针的对齐要求。对于这个虚构的平凡实现,这使得8 * 3 = 24个字节。标准库使用的实际实现可能类似。

答案 3 :(得分:0)

容器std::list是一个链表,因此它分配的节点不仅包含您的元素,还包含两个指针:一个指向下一个节点的指针和一个指向前一个节点的指针。

如果您想要更高效的内存容器,请考虑使用std::vector并使用std::vector::reserve函数预分配内存。