堆与堆栈分配

时间:2011-07-15 22:00:27

标签: c++

我对在堆上分配对象和在堆栈上分配的主题,以及应该何时以及如何调用delete()这一点感到困惑。

例如我有类Vector。我想做一些这些。

我可以这样做

Vector** v = new Vector*[100]; //create an array of 100 pointers to 100 Vector objects

据我所知,这会在堆上分配所有内容(除指针地址外)? 所以为了释放记忆,我需要:

for (int i = 0; i < 100; ++i)
{
   delete(v[i]);
}
delete(v);

或者只是

delete(v);

够了吗?

另一个例子:

Vector* v = Vector[100];

在这种情况下发生了什么?分配在哪里发生?堆还是堆? 我还需要打电话吗

delete(v);

但这不是全部问题,对不起,长篇大论......

示例:

class Vector
{
  int x, y, z;
}

Vector* v = new Vector();

是否分配了x,y,z?堆或堆?

或者如何:

class Vector2
{
   int items[10];
}

Vector2* v2 = new Vector2();

分配的项目[10]在哪里? 如何删除v2?我需要自定义析构函数吗?

最后但并非最不重要的是这个:

class Vector3
{
   int* items;
}

Vector3 v3 = Vector3();

项目指针存储在哪里?堆还是堆栈?我该如何删除?

非常感谢和抱歉。我已经很长时间没遇到这些东西,并且无法在线找到任何完整的解释。

4 个答案:

答案 0 :(得分:13)

我会从头开始......

Vector** v = new Vector*[100];

在堆上为指向Vector类型的对象分配100个指针的数组 它返回一个指针-v-您可以用它来跟踪这个指针数组。

使用以下命令删除此100个数组:

delete[] v;

(对于单个分配的对象使用delete运算符 - delete,对于数组使用delete[]

下一个案例(我假设你的意思是new Vector[100]

Vector* v = new Vector[100];

您在堆上分配了一个包含100个向量的数组,并获得了指向其起始位置的指针-v。 使用以下命令删除此数组:

delete[] v;

下一步...

class Vector
{
  int x, y, z;
}

Vector* v = new Vector();

这会在堆上分配Vector类的对象,并为您提供一个指针来跟踪它。因为您在堆上分配了整个对象,所以x,y和z都在堆上分配。

删除它:

delete v;


class Vector2
{
   int items[10];
}

Vector2* v2 = new Vector2();

这个有点棘手,但我要推理出来......

课程是蓝图。在以某种方式实例化类之前,您根本没有分配任何内存,在本例中是在堆上。由于该类是蓝图,因此在堆上创建类items的对象之前,无法分配Vector2。我认为我们可以合理地推断出items因此被分配在堆上。

删除v2:

delete v2;

最后:

class Vector3
{
   int* items;
}

Vector3 v3 = Vector3();

您在堆栈上分配了所有类Vector3,因此也分配了它内部的指针items。堆上没有任何东西,所以不要删除它。

答案 1 :(得分:9)

让我们明星你可能不需要动态分配任何东西 无论是静态数组还是向量都可以更好地工作。

但是我们假设你这样做是为了学习练习。

1分配指针数组

Vector** v = new Vector*[100]; //create an array of 100 pointers to 100 Vector objects
                               //
                               // The above comment is misleading.
                               // The 100 pointers have not been initialized.

这分配了一个内存区域,其中有100个指针的空间(对于Vector(注意它们是未初始化的,即每个指针是随机的))。要删除它,您需要执行以下操作:

delete [] v;

2分配数组成员

如果您分配了每个成员(如果您想使用它们,您应该这样做:

for (int i = 0; i < 100; ++i)
{
   v[i] = new Vector;
}

// Code

for (int i = 0; i < 100; ++i)
{
   delete v[i];
}

请注意,对于每次调用new,都应该有相应的删除调用。

3错误

Vector* v = Vector[100];

这是错的。如果不编译。

4会员去哪里

除非成员是指针,否则它在对象内 如果成员是指针,则必须单独分配。

class Vector
{
  int x, y, z;
}

Vector* v1 = new Vector();
Vector  v2 = Vector();      // Yes the = Vector() is required

这里v1指向包含x / y / z的动态分配对象 这里v2是一个包含x / y / z

的对象

我知道人们会说= Vector();是不需要的或复制结构。两种都是真的,但都错过了重点。 1)它是一个复制结构,但编译器总是足够智能删除它。 2)需要使其等同于上面的行。区别在于default-initialized(即未初始化),成员为zero-initialized(因为Vector()只有编译器生成的构造函数)。

那么阵列成员呢 他们与其他成员没有什么不同。成员在对象内部始终分配。如果成员是指针,那么它就在对象内部,但它指向的内容必须明确设置。

class Bob
{
    int   dataArray[10];
    int*   dataPtr;
};
Bob  b1 = Bob();
Bob* b2 = new Bob();

b1.dataArray[0] = 1;            // dataArray is inside the object.
                                // b1 is allocated locally

b1.dataPtr      = new int [10]; // dataPtr is inside the object.
                                // But what it points at must be seprotally defined.
                                // Note you must call delete [] for each new []
b1.dataPtr[5] = 2;

b2->dataArray[0] = 1;           // dataArray is inside the object.
                                // b2 is allocated dynamically

b2->dataPtr      = new int [10];// dataPtr is inside the object.
                                // But what it points at must be aseptically defined.
                                // Note you must call delete [] for each new []
b2->dataPtr[5] = 2;

答案 2 :(得分:2)

一般规则:

  • 当你使用newnew []时,你在堆上分配,在其他情况下你在堆栈上分配。

  • 每次使用new时,都应使用delete(明确与否)

  • 每次使用new[]时,都应使用delete[](明确与否)

下一个代码是UB,因为你使用了一个新的[]和101删除。使用一个delete[]

Vector** v = new Vector*[100];
for (int i = 0; i < 100; ++i)
{
   delete(v[i]);
}
delete(v);

答案 3 :(得分:1)

  1. delete [] v; - 这是删除操作符的数组表示法。删除数组时必须使用它,而不是按顺序删除每个元素。
  2. Vector* v = Vector[100];只是不会编译。写Vector v[100];,它将在堆栈上分配向量数组。您不能手动删除它。
  3. x, y, z在堆上,因为整个对象在堆上
  4. items[10]也在堆上分配,因为它是对象的一部分。要删除它,只需致电delete v2;。除非在构造函数中分配任何内容,否则不需要特殊的析构函数。
  5. int* items;存储在堆栈中,因为它是堆栈上分配的对象的一部分。您不必删除它,当它超出范围时将自动删除。