【问题标题】:Where does a std::vector allocate its memory?std::vector 在哪里分配内存?
【发布时间】:2012-04-28 18:43:52
【问题描述】:

考虑以下代码sn-p:

#include <vector>
using namespace std;

void sub(vector<int>& vec) {
    vec.push_back(5);
}

int main() {
    vector<int> vec(4,0);
    sub(vec);
    return 0;
}

假设“vec”没有剩余空间来存储“sub”函数中的5,它在哪里分配新内存?

在子函数的栈帧中?在这种情况下, 5 将在子函数的末尾被删除。但是主函数的栈帧不能增长,因为此时子函数的栈帧位于栈顶。
std::vector 是否为其在堆上的元素分配内存? 但是它是如何释放堆内存的呢? 如果是栈上的局部向量,包含该向量的函数的栈帧最后会被删除,而不通知向量将被删除?

【问题讨论】:

  • 你可能想看看 STL 分配器。
  • sub(vector&lt;int&gt;&amp; vec) 称为sub(vec) 肯定更容易阅读;)
  • 在堆上分配内存 std::vector Implementation

标签: c++ memory-management stl vector


【解决方案1】:

std::vector 是否为其在堆上的元素分配内存?

是的。或者更准确地说,它是根据您在构建时传入的分配器进行分配的。你没有指定一个,所以你得到了默认的分配器。默认情况下,这将是the heap

但是它是如何释放堆内存的呢?

当它超出范围时通过它的destructor。 (请注意,指向超出范围的向量的 指针 不会触发析构函数)。但是,如果您按值传递给sub,您将构建(然后破坏)一个新副本。然后 5 将被推回该副本,该副本将被清理,main 中的向量将保持不变。

【讨论】:

【解决方案2】:

STL 中的所有容器都使用模板参数进行参数化,通常最后一个参数称为AAllocator,默认为std::allocator&lt;...&gt;,其中... 表示存储在容器中的值的类型。

Allocator 是一个类,用于提供内存和构建/销毁此内存区域中的元素。它可以从池中分配内存,也可以直接从堆中分配内存,无论您从哪个构建分配器。默认情况下,std::allocator&lt;T&gt;::operator new 的简单包装器,因此将按照您的推断在堆上分配内存。

内存是按需分配的,至少在调用vector 的析构函数时会被释放。 C++11 也引入了shrink_to_fit 来更快地释放内存。最后,当向量超出其当前容量时,会进行新的(更大的)分配,将对象移动到其中,并释放旧的分配。

和所有的局部变量一样,析构函数在执行到它被声明到的作用域的末尾时被调用。所以,在函数退出之前,向量析构函数被调用,然后堆栈收缩,控制权返回给调用者。

【讨论】:

    【解决方案3】:

    另请注意,您的向量 (vec) 是对象本身。它驻留在堆栈上,当此对象超出范围时(在您的情况下是 main 的结尾),它会被破坏。元素的内存是在这个对象的初始化过程中分配的,并随着它的销毁而释放,这是RAII 习惯用法的一个很好的例子,因为元素的资源管理与向量对象的生命周期相关。

    【讨论】:

      【解决方案4】:

      因为你在堆中给了 sub 向量的地址,所以它会在堆中分配。如果没有剩余空间,应该抛出异常。

      【讨论】:

      • 堆上的向量和它在堆上分配内存之间绝对没有联系。
      • 向量不在“堆”上,不管它是什么。它在main 的堆栈中。
      • 无论你是在栈上还是在堆上分配一个向量,默认实现总是在堆上分配它的内存。
      • 至少这是我想说的。考虑到我说得不够准确。我的错!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-10-11
      • 1970-01-01
      • 2012-10-08
      • 2015-09-24
      • 1970-01-01
      相关资源
      最近更新 更多