【问题标题】:How the memory allocation works for nested containers?嵌套容器的内存分配如何工作?
【发布时间】:2015-12-05 23:17:36
【问题描述】:

例如,我有std::vector<std::string>vectorstring 的分配器如何协同工作?

假设vector 的分配器分配了一块内存ChunkVec,那么string 的分配器是否在ChunkVec 内部分配内存,以便为每个string 分配的内存总和为ChunkVec?还是string 的分配器在ChunkVec 之外分配内存?

其他嵌套容器的答案是否相同?

C++和C++11有区别吗?

【问题讨论】:

  • 你在找this
  • 您可以简单地遍历向量,打印迭代器当前指向的位置的地址,然后您可以将您的字符串元素分解为 C 字符串(参见 here)并分析两者的内存布局。由于 C++0x,std::vector 也必须将其元素存储在 continuous manner 中,因此应该很容易看到什么在哪里。

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


【解决方案1】:

我有 std::vector

在我的 64 位 Ubuntu 15.04 上,无论内容如何,​​std::string 都是 8 个字节。

(使用 std::string s1;我正在比较 sizeof(std::string) 与 s1.size()。然后附加到字符串,然后再次打印它们。)

我没有注意到或找到一种方法来指定当字符串从堆中分配其数据时要使用的分配器,因此,我相信它必须使用一些标准分配器,可能是新的,但我从未研究过标准: :字符串代码。而那个标准分配器对你的向量一无所知。

字符串分配器是否在 ChunkVec 内分配内存,以便 为每个字符串分配的内存总和为 ChunkVec?

我相信向量元素中的字符串部分只是指向字符串“正确”在堆中所在位置的 8 字节指针。所以没有。

或者字符串的分配器在 ChunkVec 之外分配内存?

是的,我相信是的。

您可以通过打印向量元素 i 和 i+1 的地址以及元素 i 的某些字符的地址来确认这一点。

顺便说一句,在我的实现 (g++ 4.9.2) 中,sizeof(std::vector) 是 24 字节,无论数据元素的数量 (vec.size()) 和元素大小如何。另请注意,我已经阅读了一些实现,其中一些小向量实际上可能驻留在 24 个字节中。实现细节可能很乏味,但很有帮助。不过,有些人可能会对您为什么想知道这一点感兴趣。


请注意,我们正在讨论实现细节(我认为)......所以您的探索可能与我的不同。


其他嵌套容器的答案是否相同?

我没有探索每个容器(但我使用了很多“std::vector”)。

一般来说,不用多想,我猜不会。

C++和C++11有区别吗?

实施细节因各种原因而发生变化,包括语言功能变化。你试过什么?

【讨论】:

  • std::stringstd::basic_string< char, std::char_traits<char>, std::allocator<char> > 的 typedef 从这个事实来看,找到一种方法来使用带有不同分配器的字符串应该很容易。
  • Ben Voigt 知道他在说什么。此外,sbabbi 指出他预计您的下一个问题可能是“我如何……”
  • 如果您的 std::string 有 8 个字节大,那么它(很可能)使用了不符合 C++11(COW 字符串)的实现。
【解决方案2】:

std::string 有两件事要存储——字符串的大小和内容。如果我在堆栈上分配一个,大小也将在堆栈上。对于短字符串,字符数据本身也将在堆栈上。这两项构成了“控制结构”。 std::string 仅将其分配器用于不适合其固定大小控制结构的长字符串。

std::vector 分配内存来存储std::string 的控制结构。 std::string 存储长字符串所需的任何分配都可能位于与向量完全不同的内存区域中。短字符串将完全由std::vector 的分配器管理。

【讨论】:

    【解决方案3】:

    ChunkVec 只存储指向由字符串分配的数据的指针。(在这种情况下,它存储一个存储指针的 std::string 对象)。它是一个完全不同的分配。理解它的一个好方法是在编程中分析树结构。

    struct node  
    {
         int data;
         struct node* left;
         struct node* right;
    };
    

    left 和 right 是与 node 不同的内存分配。您可以在不删除此节点的情况下删除它们。

    【讨论】:

      猜你喜欢
      • 2013-05-17
      • 1970-01-01
      • 1970-01-01
      • 2021-01-09
      • 2014-06-08
      • 1970-01-01
      • 2021-11-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多