如何销毁动态分配的动态对象数组?
How do I destruct a dynamically allocated array of dynamic object?
我写了一个classvector
,它的成员是一个动态分配的数组
template <typename T> struct vector{
T* elem;int capacity;
/*
*capacity is the size of array, not number of elements in the array .
*the default capacity is 3.
*/
vector(int c=3,T e=0){ /* initializing all elements as e */
T* elem=new T[capacity = c];
for(int i=0;i<capacity;i++){
elem[i]=e;
}
}
~vector(){
delete[] elem;
}
};
现在是重点,关于 vector
的析构函数。如果成员elem
中的元素也是动态分配的对象obj
,而这个对象也有自己的析构函数
int main(){
vector<obj*> vec;
vec.elem[0] = new obj(parameter)
vec.elem[1] = new obj(parameter)
vec.elem[2] = new obj(parameter)
...
}
是否有必要delete
vector
的析构函数中的所有对象?像这样
~vector(){
for(int i=0;i<capacity;i++){
delete elem[i];
}
delete[] elem;
}
或者我应该只 delete[] elem
而 obj
的析构函数将完成其余的工作?
Is it necessary to delete all the objects in the destructor of vector? like this
技术上是的,但是如果你想要一个不代表所有权的指针向量怎么办?您很容易以两次删除对象或尝试删除基于堆栈的对象而告终:
obj obj_a;
obj* obj_b = new obj;
vector<obj*> obj_ptrs;
obj_ptrs.elem[0] = &obj_a;
obj_ptrs.elem[1] = &obj_a;
obj_ptrs.elem[2] = obj_b;
delete obj_b;
是否需要用vector删除指向的对象是vector的业务none.
最干净的解决方法是使用 std::unique_ptr
,它是一个对象类型,它包含一个指针并在它被销毁时将其删除:
#include <memory>
template <typename T> struct vector {
// ...
~vector() {
// The vector is only responsible for deleting the array.
delete[] elem;
}
};
// ...
void foo() {
vector<std::unique_ptr<obj>> obj_ptrs;
obj_ptrs.elem[0] = std::make_unique<obj>();
obj_ptrs.elem[1] = std::make_unique<obj>();
obj_ptrs.elem[2] = std::make_unique<obj>();
obj stack_obj;
vector<obj*> obj_no_own_ptrs;
obj_no_own_ptrs.elem[0] = obj_ptrs.elem[0].get();
obj_no_own_ptrs.elem[1] = obj_ptrs.elem[0].get();
obj_no_own_ptrs.elem[2] = &stack_obj;
// Everything gets deleted
// No double-delete concern
}
一般来说,当您在对象中调用 delete 时,它首先调用 class 的析构函数,然后释放分配对象的内存。
所以,是的。如果您创建一个 class 调用向量,则如果 elem 在之前使用 new.
动态分配,则有必要调用 delete
新总是要与删除配对。标准方法是,例如将 new 放在构造函数中,将 delete 放在 class.
的析构函数中
在你的情况下,在你的 class 中,你正在为其他 class 动态分配 space,这恰好也是一个动态分配的指针。
first_object->second_object->third_object...
在这种情况下 first_object 包含到 second_object
的动态分配向量。 second_object
当然可以包含更多动态分配的内存。
在 first_object
的析构函数中,您删除了 second_object
,因此调用第二个对象的析构函数并释放其内存。调用 second_object
的析构函数应该删除第三个对象,因此它的内存也被释放。
如果您分配内存但不取消分配,您就会开始弄乱内存,因为您正在对它进行碎片化处理。如果你在没有 new 的情况下调用 delete,或者在一个已经被删除的对象中,将会出现段错误。将新闻放在构造函数中并在析构函数中删除总是一个好主意。
现在您也可以使用 shared_ptr
或 unique_ptr
。他们会在超出范围时自动删除其内容。
特别是 shared_ptr
将在指向一个资源的最后一个指针超出范围时删除其内容
unique_ptr
将在超出范围时删除其内容,因为根据定义禁止多个指针指向其内容。
{
std::shared_ptr foo = std::make_shared();
std::shared_ptr foo2(new Foo());
}
两个共享指针在超出范围时会自动删除其内容。第一个选项是首选且更有效(make_shared 比使用 new 调用构造函数更好)。您还可以使用 unique_ptr
,其特性与 shared_ptr 相似,它们不允许超过一个指针指向同一资源。
我认为您可以阅读有关 智能指针 和 RAII 的文章,它会对您有所帮助
我写了一个classvector
,它的成员是一个动态分配的数组
template <typename T> struct vector{
T* elem;int capacity;
/*
*capacity is the size of array, not number of elements in the array .
*the default capacity is 3.
*/
vector(int c=3,T e=0){ /* initializing all elements as e */
T* elem=new T[capacity = c];
for(int i=0;i<capacity;i++){
elem[i]=e;
}
}
~vector(){
delete[] elem;
}
};
现在是重点,关于 vector
的析构函数。如果成员elem
中的元素也是动态分配的对象obj
,而这个对象也有自己的析构函数
int main(){
vector<obj*> vec;
vec.elem[0] = new obj(parameter)
vec.elem[1] = new obj(parameter)
vec.elem[2] = new obj(parameter)
...
}
是否有必要delete
vector
的析构函数中的所有对象?像这样
~vector(){
for(int i=0;i<capacity;i++){
delete elem[i];
}
delete[] elem;
}
或者我应该只 delete[] elem
而 obj
的析构函数将完成其余的工作?
Is it necessary to delete all the objects in the destructor of vector? like this
技术上是的,但是如果你想要一个不代表所有权的指针向量怎么办?您很容易以两次删除对象或尝试删除基于堆栈的对象而告终:
obj obj_a;
obj* obj_b = new obj;
vector<obj*> obj_ptrs;
obj_ptrs.elem[0] = &obj_a;
obj_ptrs.elem[1] = &obj_a;
obj_ptrs.elem[2] = obj_b;
delete obj_b;
是否需要用vector删除指向的对象是vector的业务none.
最干净的解决方法是使用 std::unique_ptr
,它是一个对象类型,它包含一个指针并在它被销毁时将其删除:
#include <memory>
template <typename T> struct vector {
// ...
~vector() {
// The vector is only responsible for deleting the array.
delete[] elem;
}
};
// ...
void foo() {
vector<std::unique_ptr<obj>> obj_ptrs;
obj_ptrs.elem[0] = std::make_unique<obj>();
obj_ptrs.elem[1] = std::make_unique<obj>();
obj_ptrs.elem[2] = std::make_unique<obj>();
obj stack_obj;
vector<obj*> obj_no_own_ptrs;
obj_no_own_ptrs.elem[0] = obj_ptrs.elem[0].get();
obj_no_own_ptrs.elem[1] = obj_ptrs.elem[0].get();
obj_no_own_ptrs.elem[2] = &stack_obj;
// Everything gets deleted
// No double-delete concern
}
一般来说,当您在对象中调用 delete 时,它首先调用 class 的析构函数,然后释放分配对象的内存。
所以,是的。如果您创建一个 class 调用向量,则如果 elem 在之前使用 new.
动态分配,则有必要调用 delete新总是要与删除配对。标准方法是,例如将 new 放在构造函数中,将 delete 放在 class.
的析构函数中在你的情况下,在你的 class 中,你正在为其他 class 动态分配 space,这恰好也是一个动态分配的指针。
first_object->second_object->third_object...
在这种情况下 first_object 包含到 second_object
的动态分配向量。 second_object
当然可以包含更多动态分配的内存。
在 first_object
的析构函数中,您删除了 second_object
,因此调用第二个对象的析构函数并释放其内存。调用 second_object
的析构函数应该删除第三个对象,因此它的内存也被释放。
如果您分配内存但不取消分配,您就会开始弄乱内存,因为您正在对它进行碎片化处理。如果你在没有 new 的情况下调用 delete,或者在一个已经被删除的对象中,将会出现段错误。将新闻放在构造函数中并在析构函数中删除总是一个好主意。
现在您也可以使用 shared_ptr
或 unique_ptr
。他们会在超出范围时自动删除其内容。
特别是
shared_ptr
将在指向一个资源的最后一个指针超出范围时删除其内容unique_ptr
将在超出范围时删除其内容,因为根据定义禁止多个指针指向其内容。{
std::shared_ptr foo = std::make_shared();
std::shared_ptr foo2(new Foo());
}
两个共享指针在超出范围时会自动删除其内容。第一个选项是首选且更有效(make_shared 比使用 new 调用构造函数更好)。您还可以使用 unique_ptr
,其特性与 shared_ptr 相似,它们不允许超过一个指针指向同一资源。
我认为您可以阅读有关 智能指针 和 RAII 的文章,它会对您有所帮助