如何知道何时在 C++ 中调用 delete 以及何时调用 delete[]?

How to know when to call delete and when delete[] in C++?

我正在实现模仿标准库智能指针 std::unique_ptrstd::shared_ptr 的 classes my_unique_ptrmy_shared_ptr 以更好地了解它。

在实现析构函数时,我很难决定是使用 delete 还是 delete[] 来释放内存。正如我在 SO 和其他网站上阅读的那样,没有 可移植的方式 知道 new[] 分配了多少字节(或者是否使用了 newnew[]) (How many bytes were allocated by new?)

在实现 class my_unique_ptr 时,我无法知道用户将从构造函数请求多少字节,即

他会不会my_unique_ptr<int> ptr1(new int)

或者他会做 my_unique_ptr<int> ptr1(new int[5])

如果有办法请告诉我!

这是我的 class(经过简化且没有 cpy/move 构造函数):

template<typename ValueType>
class my_unique_ptr {

    ValueType *internal_ptr = nullptr;

public:
    
    // Default constructor
    my_unique_ptr() {
       internal_ptr = nullptr;
    }

    // Paramterized constructor
    explicit my_unique_ptr(ValueType *ptr) {
       if (ptr)
        internal_ptr = ptr;
    }

    // Destructor
    ~my_unique_ptr() {
       
        // How do I know whether to use
           delete ptr;

        // or
           delete[] ptr;
        
     }

我在某处读到编译器会跟踪 new[] 的参数,然后 delete[] 使用它来正确释放内存。另请阅读“程序员有责任将 newdelete 匹配,将 new[]delete[] 匹配”。但是我如何在我的 class 中对此进行编程,以便它始终匹配正确的运算符?

旁注:

运行 valgrind 而在任何地方都使用 delete 而不是 delete[] 并传递超过 1 个 int (比如 new int[5])我的构造函数 Valgrind 说所有的内存块都被释放了,没有泄漏的机会! (尽管显示 mismatched new[] with delete 之类的警告。这是否意味着 delete 成功释放了 new[] 分配的所有 5 ints?请帮忙。 我在 Ubuntu 18.04 并使用 gcc 7.5.0.

你说得对,你不知道内存是由 new 还是 new[] 分配的。但是你甚至不知道一个内存存储了一个自动持续时间对象。例如。您的用户可以:

int a = 24;

my_unique_ptr<int> ptr1(&a); // oups

你无法知道这一点。所以做标准库做的事情:

  • 对数组类型进行专门化,例如template <class T> class my_unique_ptr<T[]> 在析构函数上调用 delete[]

  • 要求my_unique_ptr<T>必须使用从new获得的内存进行初始化,my_unique_ptr<T[]>必须使用从[=12获得的内存进行初始化=].这是您图书馆的用户必须遵守的合同。不尊重就是UB

  • 通过提供 std::make_unique. Also see

    的等价物来帮助用户遵守本合同

Does this mean delete is successfully freeing all the 5 ints allocated by new[]

没有。在不是从 new 获得的内存上调用 delete 是 UB。

实际上,标准库智能指针比您的代码更方便,它们可以在调用析构函数时使用什么运算符(delete 或 delete[])。它们默认采用delete,如果你想使用delete[],你应该将它提供给智能指针构造函数。除此之外,如果您创建单个对象,请使用 new 和 delete。如果你创建一个数组,使用 new[] 来创建它,使用 delete[] 来删除它。