ChatGPT解决这个技术问题 Extra ChatGPT

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

以下所有陈述都是正确的吗?

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. 

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


2
2 revs
vector<Type> vect;

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

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

分配免费存储中的所有内容。

vector<Type*> vect;

将在堆栈上分配 vector 并在空闲存储上分配一堆指针,但这些点的位置取决于您如何使用它们(例如,您可以将元素 0 指向空闲存储,将元素 1 指向堆栈)。


但是我有一个场景,当 Type 在第二个声明中变大时,我遇到了分段错误。我假设这是因为 Type 被分配在堆栈上。
@Phelodas:没有看到你的代码,这是不可能评估的。请打开一个新问题。
关于vector<Type> vect;,由于元素在堆上,头信息在栈上,当头信息从内存中删除时,如函数返回,元素内存会发生什么?它们是否与标题信息一起回收?如果不是,这会导致内存泄漏吗?
@flyrain:向量会自行清理。阅读RAII
@flyrain:应该可以。请发布一个包含更多详细信息的新问题。如果你在这里发布链接,我可能会看看它。
C
Community

向量<类型>向量; //在堆栈上分配vect并且每个类型(使用std :: allocator)也将在堆栈上

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

矢量<类型> *vect = 新矢量<类型>; //在堆上分配vect,每个类型将在堆栈上分配

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

向量<类型*>向量; //vect 将在堆栈上,而 Type* 将在堆上。

vect 将在堆栈上,它的项目(指向 Type 的指针)将在堆上,您无法确定指针指向的 Type 将在哪里。可能在堆栈上,可能在堆上,可能在全局数据中,可能无处(即 NULL 指针)。

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


F
Flexo

假设一个实现实际上有一个堆栈和一个堆(标准 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 - IIRC 在一些小型微控制器上,你有一个调用堆栈,在最后一次调用时只能存储 PC(程序计数器),为 RET 做好准备。因此,您的编译器可能会选择将“自动存储”(用于非递归函数)放置在与执行流程几乎/没有关系的固定位置。它可以非常明智地将整个程序弄平。即使对于递归情况,您也可以有一个“每个函数的堆栈”策略或一个用于自动变量和返回地址的单独堆栈,这使得“堆栈”这个短语有点毫无意义。
您可以为 everything 使用基于堆的分配,并拥有一个管理自动存储的“清理堆栈”(也可能是 delete)。
A
Alexei Khlebnikov

只有这句话是正确的:

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

Type* 指针存储在堆上,因为指针的数量可以动态变化。

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


Type* 并不表示堆分配,只是一个指向 Type 对象的指针。也就是说,向量确实将指针存储在堆上。 int a = 5; int *ptr_to_a = &a;向量 vec; vec.push_back(ptr_to_a); (见 jpalecek 的回答)
“Type* 不表示堆分配” - 同意,我没有相反的说法。 “向量确实将指针存储在堆上” - 也同意,这正是我所说的“类型*指针在堆上分配”的意思。
B
Bingo

vector 有一个内部 allocator,它负责从 heapvector element 分配/取消分配内存。因此,无论您如何创建向量,它的 element 总是分配在 heap 上。至于向量的元数据,这取决于您创建它的方式。