我对在堆上分配对象和在堆栈上分配的主题,以及应该何时以及如何调用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();
项目指针存储在哪里?堆还是堆栈?我该如何删除?
非常感谢和抱歉。我已经很长时间没遇到这些东西,并且无法在线找到任何完整的解释。
答案 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)
让我们明星你可能不需要动态分配任何东西 无论是静态数组还是向量都可以更好地工作。
但是我们假设你这样做是为了学习练习。
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;
如果您分配了每个成员(如果您想使用它们,您应该这样做:
for (int i = 0; i < 100; ++i)
{
v[i] = new Vector;
}
// Code
for (int i = 0; i < 100; ++i)
{
delete v[i];
}
请注意,对于每次调用new,都应该有相应的删除调用。
Vector* v = Vector[100];
这是错的。如果不编译。
除非成员是指针,否则它在对象内 如果成员是指针,则必须单独分配。
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)
一般规则:
当你使用new
或new []
时,你在堆上分配,在其他情况下你在堆栈上分配。
每次使用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)
delete [] v;
- 这是删除操作符的数组表示法。删除数组时必须使用它,而不是按顺序删除每个元素。Vector* v = Vector[100];
只是不会编译。写Vector v[100];
,它将在堆栈上分配向量数组。您不能手动删除它。x, y, z
在堆上,因为整个对象在堆上items[10]
也在堆上分配,因为它是对象的一部分。要删除它,只需致电delete v2;
。除非在构造函数中分配任何内容,否则不需要特殊的析构函数。int* items;
存储在堆栈中,因为它是堆栈上分配的对象的一部分。您不必删除它,当它超出范围时将自动删除。