Yes, it's legal. expr.new/10
of C++14:
An implementation is allowed to omit a call to a replaceable global
allocation function (18.6.1.1, 18.6.1.2). When it does so, the storage
is instead provided by the implementation or provided by extending the
allocation of another new-expression.
expr.delete/7
:
If the value of the operand of the delete-expression is not a null
pointer value, then:
— If the allocation call for the new-expression for the object to be
deleted was not omitted and the allocation was not extended (5.3.4),
the delete-expression shall call a deallocation function (3.7.4.2).
The value returned from the allocation call of the new-expression
shall be passed as the first argument to the deallocation function.
— Otherwise, if the allocation was extended or was provided by
extending the allocation of another new- expression, and the
delete-expression for every other pointer value produced by a
new-expression that had storage provided by the extended
new-expression has been evaluated, the delete-expression shall call a
deallocation function. The value returned from the allocation call of
the extended new-expression shall be passed as the first argument to
the deallocation function.
— Otherwise, the delete-expression will not call a deallocation
function (3.7.4.2).
So, in summary, it's legal to replace new
and delete
with something implementation defined, like using the stack instead of heap.
Note: As Massimiliano Janes comments, the compiler could not stick exactly to this transformation for your sample, if do_something
throws: the compiler should omit destructor call of f
in this case (while your transformed sample does call the destructor in this case). But other than that, it is free to put f
into the stack.