Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Strong exception guarantee for std::unique_ptr<T>::reset

Tags:

c++

c++11

Suppose I have a function reset:

template<typename T, typename... Args>
void reset(unique_ptr<T>& p, Args&&... args)
{
    // implementation (1)
    p.reset(new T(forward<Args>(args)...));

    // implementation (2)
    p = make_unique<T>(forward<Args>(args)...);
}

Am I correct that:

  1. For implementation (1), if an exception is thrown during the destruction of the original pointee of p, the new-ed memory will be leaked;

  2. For implementation (2), nothing can ever be leaked;

  3. And so we should prefer (2) to (1).

like image 634
Zizheng Tai Avatar asked Mar 12 '26 19:03

Zizheng Tai


1 Answers

As Jonathan Wakely points out, the point is moot, because behaviour of unique_ptr::reset is undefined if the destructor throws anyway.

Both versions have UB if the destructor throws, so this is not a reason to prefer one over the other.

[unique.ptr.single.modifiers] (standard draft)

3 Requires: The expression get_deleter()(get()) shall be well formed, shall have well-defined behavior, and shall not throw exceptions.


Even if the behaviour was well defined...

(1) Would not leak. unique_ptr takes ownership of the parameter before destructing the old one.

4 Effects: Assigns p to the stored pointer, and then if the old value of the stored pointer, old_p, was not equal to nullptr, calls get_deleter()(old_p). [ Note: The order of these operations is significant because the call to get_deleter() may destroy *this. — end note ]


Reasons to prefer one over the other

  • (1) requires only C++11, (2) requires C++14 or your own boilerplate for make_unique.
  • (2) doesn't have explicit call to new, so it is easier to reason about memory tidyness using the old rule of thumb: "one delete for each new".
like image 140
eerorika Avatar answered Mar 15 '26 09:03

eerorika



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!