FrozenHeart FrozenHeart - 3 months ago 16
C++ Question

What an implementation should do in case of operator new and "nested" initialization

I know that an implementation should free any allocated memory if the constructor of an object throws an exception in situation like this:

new T(); // Suppose that T() throws an exception


but what about the following code?

new T(f()); // Suppose that T() does NOT throw any exception, but f() does


What should implementation do in this case? Should it free any allocated memory then?

Answer

In the current C++ standard (C++14, as well as in the previous versions C++11 and C++03), it is unspecified whether memory is allocated before or after f() is evaluated, but in any case memory will be freed if it has been allocated; [expr.new]:

20 - If any part of the object initialization described above79 terminates by throwing an exception, storage has been obtained for the object, and a suitable deallocation function can be found, the deallocation function is called to free the memory [...]

79) This may include evaluating a new-initializer and/or calling a constructor.

Here the new-initializer is f(), so if the evaluation of f() throws an exception, the deallocation function will be called (if found).

Since C++17, the allocation of memory is sequenced before the evaluation of f(), so the memory will always be deallocated:

21 - If any part of the object initialization described above79 terminates by throwing an exception and a suitable deallocation function can be found, the deallocation function is called [...]

Note though that since memory allocation is elidable, the implementation is in practice free to omit the allocation if it can predict that an exception will be thrown.