我在学习 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)
这个问题的正确答案是肯定的,但为什么呢?
+关于此代码,我还有两个小问题:
A级
{
私人的:
整数 x;
民众:
A(int x = 8) : x(x) { };
};
int main()
{
ClonePtr<int> h(new A(7));
}
并得到一个编译器错误:C2664“无法将参数 1 从 A* 转换为 T*”
我将非常感谢您的帮助。
谢谢 :)
我们没有办法以一种或另一种方式肯定地回答这个问题,因为我们看不到传递给ClonePtr(T*)的指针类型,或者返回的指针类型clone()。这个类没有自己进行任何内存分配。
如果两个指针都被分配给new而不是被分配new[],那么delete将是正确的答案,而不是delete[]。
如果两个指针都被分配给new[]而不是被分配new,那么delete[]将是正确的答案,而不是delete。
就此而言,由于此代码获得了由其他东西分配的内存的所有权,并且通过此类的使用nullptr和移动构造函数(但不是移动赋值运算符!)很明显您正在使用 C++11 或更高版本,因此您应该通过or使用正确的所有权语义,而根本不使用原始指针。std::unique_ptrstd::shared_ptr
特别是因为你的拷贝赋值运算符不设置ptr到nullptr后delete ptr;,如果other.ptr是nullptr,留*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)));
}
| 归档时间: |
|
| 查看次数: |
85 次 |
| 最近记录: |