Basically, my question is whether the following code is valid.
void* mem = operator new(sizeof(T));
T* instance = new(mem) T;
delete instance;
If it isn’t, I’d be curious to know whether there is a way to split allocation and initialization for an object that is going to be deleted through delete obj;
.
When new is used to allocate memory for a C++ class object, the object's constructor is called after the memory is allocated. Use the delete operator to deallocate the memory allocated by the new operator.
The new operator is an operator which denotes a request for memory allocation on the Heap. If sufficient memory is available, new operator initializes the memory and returns the address of the newly allocated and initialized memory to the pointer variable.
The operator new (or better the void* operator new(size_t) variant) just allocate memory, but does not do any object construction. The new keyword calls the operator new function, but then calls the object constructor.
This does appear to be valid, as long as T
is not an array type, and is not a class with a custom operator delete
visible from its scope which is incompatible with the operator new
you invoke.
[expr.delete]/2 says the operand of delete
may be "a pointer to a non-array object created by a previous new-expression". The new-expression grammar syntax symbol does include the placement new syntax, and [expr.delete] doesn't say the previous new-expression needs to be a non-placement variety. And any new-expression including a placement new is considered to "create" an object.
The operator new
allocation function and operator delete
deallocation function involved do need to match up. operator new(sizeof(T))
will normally call the global ordinary allocation function, but to be more sure you can write ::operator new(sizeof(T))
. The deallocation function is looked up in the scope of class T
, so a static operator delete(void*);
in a class could break this.
You might want to consider exception safety, though. A straight T* p = ::new T;
is actually more equivalent to:
void* mem = ::operator new(sizeof(T));
T* p;
try {
p = ::new(mem) T;
} catch (...) {
::operator delete(mem, sizeof(T));
throw;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With