当我运行这个程序时,我为 unique ptr 的实现获得了双重释放。知道为什么会发生这种情况吗?
#include <iostream>
#include <memory>
using namespace std;
template <class T>
class UniquePtr
{
public:
UniquePtr(T* t = nullptr) : t_(t) {}
UniquePtr(const UniquePtr&) = delete;
UniquePtr& operator=(const UniquePtr& oth) = delete;
UniquePtr(UniquePtr&& oth) {
std::swap(t_, oth.t_);
}
UniquePtr& operator=(UniquePtr&& oth) {
std::swap(t_, oth.t_);
return *this;
};
~UniquePtr() {
delete t_;
}
private:
T* t_;
};
struct Obj {
Obj(int x): x_(x) { cout << "new " << x_ << endl; }
~Obj() { cout << "delete " << x_ << endl; }
int x_;
};
template <class UP>
void test(UP&&) {
{
UP ptr(new Obj(1));
}
{
UP ptr(UP(new Obj(2)));
}
{
auto lambda = []() {
UP ptr(new Obj(3));
return ptr;
};
UP ptr2(lambda());
}
}
int main() {
cout << "unique_ptr" << endl;
test(unique_ptr<Obj>());
cout << endl;
cout << "UniquePtr" << endl;
test(UniquePtr<Obj>());
cout << endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
unique_ptr
new 1
delete 1
new 2
delete 2
new 3
delete 3
UniquePtr
new 1
delete 1
new 2
delete 2
new 3
delete 3
delete 0
free(): double free detected in tcache 2
Aborted
Run Code Online (Sandbox Code Playgroud)
t_在移动构造函数中未初始化,因此移动自指针最终指向未初始化的指针并具有未定义的行为(当移动自对象解构并delete保存未初始化的指针时,这将导致问题)。你需要:
UniquePtr(UniquePtr&& oth)
: t_(nullptr)
{
std::swap(t_, oth.t_);
}
Run Code Online (Sandbox Code Playgroud)
或者可能更简单:
UniquePtr(UniquePtr&& oth)
: t_(std::exchange(oth.t_, nullptr)
{
}
Run Code Online (Sandbox Code Playgroud)