正在对使用operator new okay的放置delete操作的结果调用delete



如果我做了

struct MyStruct { ~MyStruct() { } };
void *buffer = operator new(1024);
MyStruct *p = new(buffer) MyStruct();
// ...
delete p;     //    <---------- is this okay?

delete是否保证同时呼叫 ~MyStruct() operator delete ?

delete p等价于

p->~MyStruct();
operator delete(p);

除非MyStruct有一个可替代的operator delete,所以你的例子应该用预期的语义定义良好。

[expr.delete]/2状态:

delete操作数的值可以是…指向由前一个new-expression创建的非数组对象的指针。

Placement new是new-expression的类型。[expr.new]/1:

<我>新的表达式:
:: <我><子>选择<我>新的广告<子>选择 new-type-id new-initializer <子>选择
:: <我><子>选择<我>新的广告<子>选择 (<我> id类型) <我> new-initializer <子>选择

delete定义为对对象的析构函数的调用,然后对内存的释放函数的调用。[expr.delete]/6,7:

delete表达式将调用对象的析构函数(如果有的话)…

delete表达式将调用一个释放函数…

只要释放函数匹配分配函数(它应该匹配,只要您没有为您的类重载operator delete),那么这些都应该定义得很好。

[Revised]一般不可以,您只能一般delete使用匹配的普通new表达式获得的东西。否则,由您来保证释放函数与分配函数匹配(因此,使用::delete p;将是更安全的通用解决方案,假设您的原始operator new位于全局命名空间中)。特别是当有问题的类(或其派生类之一)重载operator new时,您必须小心。

由于您使用的是位置-new表达式来创建*p,并且由于没有"位置-delete表达式"这样的东西,因此您必须手动销毁对象,然后释放内存:

p->~MyStruct();
operator delete(buffer);

不,通常不应该调用delete(在某些情况下,例如当操作符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)

最新更新