Pedantically, this may not be OK. As per cppref:
If expression is anything else, including if it is a pointer obtained by the array form of new-expression, the behavior is undefined.
Putting that aside, is the following code OK in practice (T
is non-array, and assuming that new
is not replaced)?
auto p = (T*)operator new(sizeof(T));
new(p) T{};
delete p;
It is said that in cppref that
When calling the allocation function, the new-expression passes the number of bytes requested as the first argument, of type
std::size_t
, which is exactlysizeof(T)
for non-array T.
So I guess this is probably OK. However, it is also said that since C++14,
New-expressions are allowed to elide or combine allocations made through replaceable allocation functions. In case of elision, the storage may be provided by the compiler without making the call to an allocation function (this also permits optimizing out unused new-expression). In case of combining, the allocation made by a new-expression E1 may be extended to provide additional storage for another new-expression E2 if all of the following is true: [...]
Note that this optimization is only permitted when new-expressions are used, not any other methods to call a replaceable allocation function:
delete[] new int[10];
can be optimized out, butoperator delete(operator new(10));
cannot.
I'm not quite sure of the implications. So, is this OK in C++14?
Why am I asking this question? (source)
Sometimes, memory allocation and initialization cannot be done in a single step. You have to manually allocate the memory, do something else, and then initialize the object, e.g., to provide strong exception safety. In this case, if the delete expression cannot be used on the resulting pointer, you have to manually uninitialize and deallocate, which is tedious. To make things worse, in case both new expression and the manual method are employed, you have to track which one is used for each object.