Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is new T() equivalent to `mem = operator new(sizeof(T)); new(mem)T`?

Tags:

c++

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;.

like image 582
addaleax Avatar asked Apr 02 '20 01:04

addaleax


People also ask

What is new() in C++?

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.

Why use new in C++?

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.

What is :: operator new?

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.


1 Answers

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;
}
like image 150
aschepler Avatar answered Sep 19 '22 12:09

aschepler