std :: vector在哪里分配内存?

时间:2012-04-28 18:43:53

标签: c++ memory-management stl vector

请考虑以下代码段:

#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”没有空间将5存储在“sub”函数中,它在哪里分配新内存?

在子功能的堆栈框架中?在这种情况下,5将在子函数的末尾被删除。但是主函数的堆栈帧不能增长,因为子函数的堆栈帧在那一刻位于堆栈顶部。
std :: vector是否为堆上的元素分配内存? 但它如何释放堆内存呢? 如果它是堆栈上的局部向量,那么包含向量的函数的堆栈帧最终会被删除,而不会发信号通知它将被删除吗?

4 个答案:

答案 0 :(得分:35)

  

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

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

  

但它如何释放堆内存?

当它超出范围时,通过其destructor。 (注意,超出范围的向量的指针不会触发析构函数)。但是如果你已经通过值sub传递了一个新的副本,那么你构造(以后破坏)。然后将5推回到该副本,副本将被清理,main中的向量将不受影响。

答案 1 :(得分:17)

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

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

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

与所有局部变量一样,析构函数在执行时到达已声明的范围的末尾时被调用。因此,在退出函数之前,将调用向量析构函数,之后只有堆栈收缩并且控制权返回给调用者。

答案 2 :(得分:2)

另请注意,您的向量(vec)本身就是对象。它驻留在堆栈上,当此对象超出范围(在您的情况下为main的末尾)时,它将被破坏。元素的内存在此对象的初始化期间分配,并随其销毁而释放,这是RAII习语的一个可爱示例,因为元素的资源管理与向量对象的生命周期相关联。

答案 3 :(得分:0)

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