析构函数中的删除与删除[]

sha*_*ron 2 c++ oop

我在学习 C++ 考试,有人问我在这段代码中,该类的 d'tor 是否应该使用 delete[] 而不是 delete:

    template <class T>
class ClonePtr
{
private:
    T* ptr;
public:
    explicit ClonePtr(T* p = nullptr) : ptr(p) {}
    ~ClonePtr() { if(ptr!=nullptr) delete []ptr; }
    ClonePtr(const ClonePtr& other) : ptr(nullptr)
    {
        *this = other;
    }
    ClonePtr(ClonePtr&& other) : ptr(other.ptr)
    {
        other.ptr = nullptr;
    }
    ClonePtr& operator=(const ClonePtr& other)
    {
        if (this != &other)
        {
            delete ptr;
            if (other.ptr != nullptr)
                ptr = other.ptr->clone();
        }
        return *this;
    }
    T& operator*() const { return *ptr; }
};
Run Code Online (Sandbox Code Playgroud)

这个问题的正确答案是肯定的,但为什么呢?

+关于此代码,我还有两个小问题:

  1. 它在考试中说类型 T 必须是一个类,不能是原始类型。这是为什么?
  2. 另一方面,我尝试编写此代码:
A级
{
私人的:
    整数 x;
民众:
    A(int x = 8) : x(x) { };
};

int main()
{
    ClonePtr<int> h(new A(7));
}

并得到一个编译器错误:C2664“无法将参数 1 从 A* 转换为 T*”

我将非常感谢您的帮助。

谢谢 :)

Rem*_*eau 5

我们没有办法以一种或另一种方式肯定地回答这个问题,因为我们看不到传递给ClonePtr(T*)的指针类型,或者返回的指针类型clone()。这个类没有自己进行任何内存分配。

如果两个指针都被分配给new而不是被分配new[],那么delete将是正确的答案,而不是delete[]

如果两个指针都被分配给new[]而不是被分配new,那么delete[]将是正确的答案,而不是delete

就此而言,由于此代码获得了由其他东西分配的内存的所有权,并且通过此类的使用nullptr和移动构造函数(但不是移动赋值运算符!)很明显您正在使用 C++11 或更高版本,因此您应该通过or使用正确的所有权语义,而根本不使用原始指针。std::unique_ptrstd::shared_ptr

特别是因为你的拷贝赋值运算符不设置ptrnullptrdelete ptr;,如果other.ptrnullptr,留*this在一个糟糕的状态。使用适当的所有权语义可以避免这种情况。

试试这个:


更新:现在你已经发布了额外的代码(不能编译,因为 anA*不能分配给 an int*,并且A没有实现clone())显示ptr被设置为一个分配有 的对象new,所以正确的答案是:

  • delete必须使用,而不是delete[].

所以你考试的“正确答案”是错误的。

但是适当的所有权语义会更好,例如:

#include <内存>

模板 <class T>
类 ClonePtr
{
私人的:
    std::unique_ptr<T> ptr;

民众:
    ClonePtr(std::unique_ptr<T> p) : ptr(std::move(p)) {}

    ClonePtr& operator=(ClonePtr 其他)
    {
        ptr = std::move(other.ptr);
        返回 *this;
    }

    T& 运算符*() const { return *ptr; }
};

A级
{
私人的:
    整数 x;

民众:
    A(int x = 8) : x(x) { };

    std::unique_ptr<A> clone() const
    {
        返回 std::make_unique<A>(x);
        // 或:在 C++14 之前:
        // 返回 std::unique_ptr<A>(new A(x));
    }
};

int main()
{
    ClonePtr<A> h(std::make_unique<A>(7));
    // 或者,在 C++14 之前:
    // ClonePtr<A> h(std::unique_ptr<A>(new A(7)));
}