如何销毁动态分配的动态对象数组?

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)
    ...
}

是否有必要deletevector的析构函数中的所有对象?像这样

~vector(){
    for(int i=0;i<capacity;i++){
        delete elem[i];
    }
    delete[] elem;
}

或者我应该只 delete[] elemobj 的析构函数将完成其余的工作?

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_ptrunique_ptr。他们会在超出范围时自动删除其内容。

  1. 特别是 shared_ptr 将在指向一个资源的最后一个指针超出范围时删除其内容

  2. unique_ptr 将在超出范围时删除其内容,因为根据定义禁止多个指针指向其内容。

    {

    std::shared_ptr foo = std::make_shared();

    std::shared_ptr foo2(new Foo());

    }

两个共享指针在超出范围时会自动删除其内容。第一个选项是首选且更有效(make_shared 比使用 new 调用构造函数更好)。您还可以使用 unique_ptr,其特性与 shared_ptr 相似,它们不允许超过一个指针指向同一资源。

我认为您可以阅读有关 智能指针 RAII 的文章,它会对您有所帮助