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:
For implementation (1), if an exception is thrown during the destruction of the original pointee of p, the new-ed memory will be leaked;
For implementation (2), nothing can ever be leaked;
And so we should prefer (2) to (1).
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
pto the stored pointer, and then if the old value of the stored pointer,old_p, was not equal tonullptr, callsget_deleter()(old_p). [ Note: The order of these operations is significant because the call toget_deleter()may destroy*this. — end note ]
Reasons to prefer one over the other
make_unique.new, so it is easier to reason about memory tidyness using the old rule of thumb: "one delete for each new".If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With