删除前手动调用析构函数
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;
}
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;
}