12

如果我做

struct MyStruct { ~MyStruct() { } };

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

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

4

3 回答 3

13

delete p相当于

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

除非MyStruct有替代方案operator delete,因此您的示例应使用预期的语义进行良好定义。

[expr.delete]/2状态:

delete 的操作数的值可能是...指向由先前的new-expression创建的非数组对象的指针。

放置 new 是一种new-expression[expr.new]/1

new-expression :
    :: opt new new-placement opt new-type-id new-initializer opt
    :: opt new new-placement opt ( type-id ) new-initializer opt

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

...删除表达式将调用对象的析构函数(如果有)...

...删除表达式将调用释放函数...

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

于 2013-05-24T00:09:18.860 回答
12

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

由于您使用placement-new 表达式来创建*p,并且由于没有“placement-delete 表达式”之类的东西,因此您必须手动销毁对象然后释放内存:

p->~MyStruct();

operator delete(buffer);
于 2013-05-23T23:59:29.210 回答
0

不,您通常不应该调用 delete(在某些情况下,例如当 operator 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)
于 2013-05-25T01:21:03.410 回答