Reputation: 210685
If I do
struct MyStruct { ~MyStruct() { } };
void *buffer = operator new(1024);
MyStruct *p = new(buffer) MyStruct();
// ...
delete p; // <---------- is this okay?
is the delete
guaranteed to take care of both calling ~MyStruct()
as well as operator delete
?
Upvotes: 12
Views: 284
Reputation: 8325
No, you should not generally call delete (in some cases like when operator delete is overleaded it may be ok).
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)
Upvotes: 0
Reputation: 40633
delete p
is equivalent to
p->~MyStruct();
operator delete(p);
unless MyStruct
has an alternative operator delete
, so your example should be well-defined with the expected semantics.
[expr.delete]/2
states:
the value of the operand of delete may be ... a pointer to a non-array object created by a previous new-expression.
Placement new is a type of new-expression. [expr.new]/1
:
new-expression:
::opt new new-placementopt new-type-id new-initializeropt
::opt new new-placementopt ( type-id ) new-initializeropt
delete
is defined to be a call to the destructor of the object and then a call to the deallocation function for the memory. [expr.delete]/6,7
:
... the delete-expression will invoke the destructor (if any) for the object ...
... the delete-expression will call a deallocation function ...
As long as the deallocation function matches the allocation function (which it should, as long as you haven't overloaded operator delete
for your class), then this should all be well defined.
Upvotes: 13
Reputation: 477398
[Revised] It's not generally OK, and you can only generally delete
something that was obtained with the matching plain new
expression. Otherwise it is up to you to guarantee that the deallocation function matches the allocation function (so using ::delete p;
would be the safer general solution, assuming your original operator new
was in the global namespace). In particular when the class in question (or one of its derived classes) overload operator new
you have to be careful.
Since you're using a placement-new expression to create *p
, and since there is no such thing as a "placement-delete expression", you have to destroy the object manually and then release the memory:
p->~MyStruct();
operator delete(buffer);
Upvotes: 12