如果我做
struct MyStruct { ~MyStruct() { } };
void *buffer = operator new(1024);
MyStruct *p = new(buffer) MyStruct();
// ...
delete p; // <---------- is this okay?
是否delete
保证同时兼顾呼叫~MyStruct()
和 operator 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创建的非数组对象的指针。
放置 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
为你的类重载),那么这一切都应该被很好地定义。
[修改] 一般不行,一般只能用匹配的plain表达式delete
得到的东西。new
否则,由您来保证释放函数与分配函数匹配(因此 using::delete p;
将是更安全的通用解决方案,假设您的原始函数operator new
位于全局命名空间中)。特别是当有问题的类(或其派生类之一)重载operator new
时,您必须小心。
由于您使用placement-new 表达式来创建*p
,并且由于没有“placement-delete 表达式”之类的东西,因此您必须手动销毁对象然后释放内存:
p->~MyStruct();
operator delete(buffer);
不,您通常不应该调用 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)