分配向量后,它们会使用堆还是堆栈上的内存?


151

以下所有陈述是否正确?

vector<Type> vect; //allocates vect on stack and each of the Type (using std::allocator) also will be on the stack

vector<Type> *vect = new vector<Type>; //allocates vect on heap and each of the Type will be allocated on stack

vector<Type*> vect; //vect will be on stack and Type* will be on heap. 

如何Type在一个vector或任何其他STL容器中内部分配内存?


Answers:


221
vector<Type> vect;

vector在堆栈上分配,即标头信息,但在免费存储(“堆”)上分配元素。

vector<Type> *vect = new vector<Type>;

在免费商店中分配所有东西。

vector<Type*> vect;

vector在堆栈上分配,并在免费存储区上分配一堆指针,但是这些指针的位置由您的使用方式决定(例如,您可以将元素0指向免费存储区,将元素1指向堆栈)。


3
但是我遇到了一个场景,当第二个声明中的Type变大时,我遇到了分段错误。我以为是因为Type是在堆栈上分配的。
Phelodas 2011年

4
@Phelodas:看不到您的代码,这是无法评估的。请打开一个新问题。
弗雷德·福

2
大约vector<Type> vect;因为元素在堆上并且标头信息在堆栈上,所以当标头信息从内存中删除时(如函数返回),元素存储器将如何处理?是否使用标头信息来回收它们?如果不是,这会导致内存泄漏吗?
flyrain

3
@flyrain:媒介会自行清理。在RAII上阅读。
Fred Foo 2013年

1
@flyrain:应该可以。请发布一个具有更多详细信息的新问题。如果您在此处发布链接,我可能会看一下。
Fred Foo 2013年

24
vector<Type> vect; //allocates vect on stack and each of the Type (using std::allocator) also will be on the stack

不,vect将在堆栈上,但内部用于存储项目的数组将在堆上。这些项目将驻留在该数组中。

vector<Type> *vect = new vector<Type>; //allocates vect on heap and each of the Type will be allocated on stack

否。与上面相同,除了vector该类也将在堆上。

vector<Type*> vect; //vect will be on stack and Type* will be on heap. 

vect将位于堆栈上,其项(指向的指针Type)将位于堆上,并且您无法确定Type指针所指向的s在哪里。可能在堆栈上,可能在堆上,可能在全局数据中,可能在任何地方(即NULL指针)。

顺便说一句,该实现实际上可以将某些矢量(通常为小尺寸)完全存储在堆栈中。我不知道有任何这样的实现,但是可以。


23

假设实际上有一个堆栈和一个堆的实现(标准C ++不需要具有此类东西),则唯一正确的语句是最后一个语句。

vector<Type> vect;
//allocates vect on stack and each of the Type (using std::allocator) also will be on the stack

这是事实,除了最后一部分(Type不会在堆栈上)。想像:

  void foo(vector<Type>& vec) {
     // Can't be on stack - how would the stack "expand"
     // to make the extra space required between main and foo?
     vec.push_back(Type());
  }

  int main() {
    vector<Type> bar;
    foo(bar);
  }

同样地:

 vector<Type> *vect = new vector<Type>; //allocates vect on heap and each of the Type will be allocated on stack

除最后一部分外为真,并带有类似的计数器示例:

  void foo(vector<Type> *vec) {
     // Can't be on stack - how would the stack "expand"
     // to make the extra space required between main and foo?
     vec->push_back(Type());
  }

  int main() {
    vector<Type> *bar = new vector<Type>;
    foo(bar);
  }

对于:

vector<Type*> vect; //vect will be on stack and Type* will be on heap. 

的确如此,但是请注意,Type*指针将位于堆上,但是Type它们指向的实例不必是:

  int main() {
    vector<Type*> bar;
    Type foo;
    bar.push_back(&foo);
  }

在哪种情况下您不会有堆栈?我了解您是说该标准不需要它,但实际上,您什么时候会没有堆栈?
Nerdtron 2011年

3
@Nerdtron-在某些小型微控制器上的IIRC,您有一个调用堆栈,该堆栈在最后一次调用时不能存储PC(程序计数器),只能进行RET操作。因此,您的编译器可能会选择将“自动存储”(用于非递归函数)放置在与执行流程几乎没有关系的固定位置。它可以很合理地将整个程序弄平。即使对于递归情况,您也可以使用“每个函数堆栈”策略,也可以为自动变量和返回地址设置单独的堆栈,这使得“堆栈”一词毫无意义。
Flexo

您可以对所有内容使用基于堆的分配,并拥有一个“清理堆栈”来管理自动存储(可能delete也是)。
Flexo

3

只有以下陈述是正确的:

vector <Type*> vect; //vect will be on stack and Type* will be on heap.

Type* 指针分配在堆上,因为指针的数量可以动态更改。

vect 在这种情况下,它是在堆栈上分配的,因为您将其定义为本地堆栈变量。


2
Type *并不表示堆分配,只是一个指向Type对象的指针。也就是说,向量确实将指针存储在堆上。整数= 5; int * ptr_to_a =&a; vector <int *> vec; vec.push_back(ptr_to_a); (请参阅jpalecek的回答)
马修·罗素

1

向量具有内部allocator,其负责分配/解除分配从存储器中的heap用于vector element。因此,无论您如何创建向量,它element始终都会分配在上heap。至于向量的元数据,取决于您创建向量的方式。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.