【问题标题】:Memory consumption of a pointer to vector of pointers指向指针向量的指针的内存消耗
【发布时间】:2012-03-20 23:34:11
【问题描述】:

我知道指针的大小是固定的(而不是它指向的数据的大小)。现在鉴于此,假设我在全局范围内有一个数据向量,并且我声明了一个指向指向部分/全部全局数据的指针向量的指针,这将额外使用多少内存(RAM)?我在这里完全不知所措,当然会感谢一些想法/建议。我希望无论数据的复杂性如何,额外的内存消耗只是向量的大小乘以指针的固定大小(例如 8 个字节);因为它指向的数据存在于全球范围内(即,没有分配新数据;希望我已经清楚地解释了我的想法)。

表达我的问题的一些伪代码如下所示:

std::vector<data> global_data;
std::vector<data*>* my_data = new std::vector<data*>();  //-Is this even valid? 
//-Now populate the vector with pointers to data in global_data
for(int i=0; i<global_data.size(); ++i) {
   my_data->push_back(&global_data[i]);
}

那么我的问题是 RAM 中有多少额外的内存(即超过创建 global_data 已经使用的内存)被 m_data 用完了?

【问题讨论】:

  • 不要……使用……vectors……的指针……或指向vectors的指针。这几乎总是错误的做法。您确实意识到它会阻止 vector 为您管理内存,对吧?
  • Ed.. 我相信有办法解决这个问题(无论如何,这不是我的特定目的的问题).. 但是继续,请让我知道举例说明你的意思。
  • 所以,vector 的全部意义在于它管理动态分配和释放。当它的析构函数运行时,它会在它动态分配的项目上调用delete。但是,如果您正在存储指针,那么它是分配指针,而不是它指向的对象,因此当vector 超出范围时不会被删除。同样,如果你存储一个指向vector 的指针,那么你必须手动调用delete。这称为 RAII(任何 C++ 程序员都需要了解 RAII),您正在规避 vectors 为您安全管理内存的能力。
  • 您只是没有正确使用它。 vector 本身又小又便宜,不需要动态分配。它在幕后动态分配其元素,所以不用担心。

标签: c++ pointers


【解决方案1】:

my_data 将占用sizeof(std::vector&lt;data*&gt;*) 字节,并且不会超过sizeof(void*)

*my_data 会占用sizeof(std::vector&lt;data*&gt;),可以少到3 * sizeof(data**),即不超过3 * sizeof(void*)

*my_data 将管理 sizeof(data*) * my_data-&gt;capacity() 字节的动态内存。


我非常怀疑这些信息在实践中是否有用。

【讨论】:

  • @Kerrek SB:我猜你也提到了 Haatschii 的上述担忧。我想我已经涵盖了。所以目前这对我来说不是问题。
  • 我喜欢“我非常怀疑这些信息在实践中是否有用。”
【解决方案2】:

如果我理解你的问题,你想知道你的向量消耗了多少内存。这将是指针(32 位或 64 位)的固定大小乘以存储在其中的指针数量,再加上一些用于大小字段和内容的额外字节。因此,在大多数情况下,您将无法识别它使用的内存。

但是,您绝对不应该像在代码示例中那样做。因为 std::vector 我改变了它保存数据的位置。例如。如果你 push_back 新对象,它最终将不得不分配新内存并将数据复制到新分配的空间,因为它保证数据空间是连续的。然后它将释放之前使用的内存。然后,您的旧指针将指向您的程序不再使用的空间,如果您尝试使用它们,则会导致分段错误。

【讨论】:

  • 这是关于 push_back 可能重新分配的一个很好的警告。在读取指针之前使用 reserve() 可能会解决该问题(或者如果 OP 的代码在指针数组之前填充“主”数组,则可能不会出现问题)。
  • @Haatschii .. 我知道这是一种不好的做法。但是我已经没有其他想法来优化代码了。我在一个足够安全的地方做这件事(global_data 不会有任何变化)。反正题外话..
【解决方案3】:

由于“虚拟内存”,要使用多少“RAM”并不是那么简单,但我们可以谈论将消耗多少虚拟内存。而且答案大致如你所料,再加上一点:

  • 向量中的元素数量 * 每个元素的大小(即指针的大小)。
  • 在向量中加上一些额外的“容量”,用于避免不断调整大小(可能是大小的一些小的常数因子,您可以通过调用 capacity() 来查询它)。
  • 加上向量的实现细节,例如:三个指针(开始、结束、开始 + 容量)。

如果你想用 C++ 来表达,你可以这样做:

sizeof(vector<data*>) + my_data.capacity() * sizeof(data*);

请注意,这只是给您一个粗略的猜测,而忽略了更复杂的部分,例如是否需要更多“RAM”来实际映射您在应用程序空间中使用的内存,以及您的标准分配器的行为系统等。但就C++和虚拟内存而言,我认为这是一个合理的近似。

【讨论】:

  • 欣赏简洁的回应。这对我来说听起来很正确(至少这是我希望听到的)。在我接受它之前(由于我自己对 C++ 缺乏全面的了解),我会等待其他用户的评论。再次感谢。
【解决方案4】:

回复:我希望额外的内存消耗只是向量的大小乘以指针的固定大小(比如 8 字节),而不管数据的复杂性如何;因为它指向的数据存在于全局范围内(即,没有分配新数据;希望我已经清楚地解释了我的想法)。

你基本上是对的。对于std::vector 的任何合理实现,std::vector&lt;T&gt; 的底层存储只是T 的紧凑数组。在这种情况下,您的 T 是指针类型 data * 而不是 data

可能有一些额外的存储空间用于有效扩展,否则每个push_back 操作都必须增大阵列。 (看看std::vectorreservecapacity 函数。)

当然,分配向量对象本身也有一些小的开销。

【讨论】:

  • 感谢@Kaz 的回复
【解决方案5】:

vector 的内存消耗和你猜的差不多。没错,向量的大小将与data 的布局无关。

至于实际计算向量的总大小,有两个部分起作用:

  1. 实际的矢量对象本身。向量有一些内部结构,例如,它有一个指向其内部数组的指针。此外,它的所有字段都与某些值对齐。可以使用sizeof(vector&lt;data*&gt;) 找到任何向量的总大小(包括对齐)。在我的机器上,这给出了 24

  2. 内部数组的大小。这不是基于向量的size(),而是实际上取决于向量的capacity()。总大小将为my_data-&gt;capacitiy() * sizeof(data*)。我相信数组元素之间没有填充,但如果有,这也必须考虑在内。

那么总内存消耗就是#1 和#2 的总和。

【讨论】:

    猜你喜欢
    • 2011-08-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-08
    • 1970-01-01
    • 2019-09-10
    • 1970-01-01
    相关资源
    最近更新 更多