删除前手动调用析构函数

Manually calling destructor before delete

auto obj = new Object;
obj->~Object();
delete obj;

我知道这很不寻常,但它是定义的行为吗?它会导致任何令人惊讶的问题吗?

你只能这样做如果你用一个新对象替换obj指向的被破坏的对象:

auto obj = new Object;
obj->~Object();

new (obj) Object();
delete obj;

否则,您将调用未定义的行为。


你应该明白:

  • new调用operator new获取内存,然后调用提供的构造函数创建对象
  • delete调用对象的析构函数,然后调用operator delete到"return"内存。


编辑:正如 Bo Persson 指出的那样,如果您不能提供异常保证,那不是一个好主意

导致对象析构函数被调用两次是未定义行为。你没有遵守规则,编译器可以随心所欲地处理你的代码。只是 不要那样做

如果我们严格遵守标准语言,您的代码会导致未定义的行为并会导致问题。

但是,如果任何平台 运行 出现以下任何问题,我将感到非常惊讶:

struct Foo {};

void testFoo()
{
   Foo* foo = new Foo();
   foo->~Foo();
   foo->~Foo();
   foo->~Foo();
   foo->~Foo();
   foo->~Foo();
   foo->~Foo();
   foo->~Foo();
   delete foo;
}

另一方面,如果有任何平台可以执行以下操作而不 运行 遇到问题,我会感到非常惊讶。

struct Bar {std::string s;};

void testBar()
{
   Bar* bar = new Bar{"test"};
   bar->~Bar();
   delete bar;
}