如果我这样做
struct MyStruct { ~MyStruct() { } };
void *buffer = operator new(1024);
MyStruct *p = new(buffer) MyStruct();
// ...
delete p; // <---------- is this okay?
delete
是否可以保证两者调用~MyStruct()
以及 operator delete
?
答案 0 :(得分:13)
delete p
相当于
p->~MyStruct();
operator delete(p);
除非MyStruct
有替代operator delete
,否则您的示例应该使用预期的语义进行良好定义。
[expr.delete]/2
州:
delete的操作数的值可以是......指向前一个 new-expression 创建的非数组对象的指针。
Placement new是一种 new-expression 。 [expr.new]/1
:
新表达的:
:: opt new new-placement opt new-type-id new-initializer 选择子> 的
:: opt new new-placement opt ( type-id ) new-initializer opt
delete
被定义为对对象的析构函数的调用,然后调用内存的释放函数。 [expr.delete]/6,7
:
... delete-expression 将调用对象的析构函数(如果有的话)......
... delete-expression 将调用释放函数...
只要解除分配函数与分配函数匹配(只要你没有为你的类重载operator delete
),那么这一切都应该很好地定义。
答案 1 :(得分:12)
[已修订]通常情况下并不正常,您通常只能delete
使用匹配的普通new
表达式获得的内容。否则,您可以保证解除分配函数与分配函数匹配(因此,假设您的原始::delete p;
位于全局命名空间中,使用operator new
将是更安全的通用解决方案。特别是当有问题的类(或其派生类之一)超载operator new
时,你必须小心。
由于您正在使用placement-new表达式来创建*p
,并且由于没有“placement-delete expression”这样的东西,您必须手动销毁该对象然后释放内存:
p->~MyStruct();
operator delete(buffer);
答案 2 :(得分:0)
不,你通常不应该调用delete(在某些情况下,例如当操作员删除被过度使用时,可能没问题)。
char *buffer = new char[1024];
MyStruct *p = new(buffer) MyStruct(); //placement new "i'm just calling constructor"
p->~MyStruct(); //destroy the object.
//delete p; // WHAT? even if you override operator delete it may be opaque to reader.
delete [] buffer; // THIS DELETE IS OK (if you have first destroyed MyStruct)