A recent question (and especially my answer to it) made me wonder:
In C++11 (and newer standards), destructors are always implicitly noexcept
, unless specified otherwise (i.e. noexcept(false)
). In that case, these destructors may legally throw exceptions. (Note that this is still a you should really know what you are doing-kind of situation!)
However, all overloads of std::unique_ptr<T>::reset()
are declared to always be noexcept
(see cppreference), even if the destructor if T
isn't, resulting in program termination if a destructor throws an exception during reset()
. Similar things apply to std::shared_ptr<T>::reset()
.
Why is reset()
always noexcept, and not conditionally noexcept?
It should be possible to declare it noexcept(noexcept(std::declval<T>().~T()))
which makes it noexcept exactly if the destructor of T
is noexcept. Am I missing something here, or is this an oversight in the standard (since this is admittedly a highly academic situation)?
std::unique_ptr::resetDestroys the object currently managed by the unique_ptr (if any) and takes ownership of p. If p is a null pointer (such as a default-initialized pointer), the unique_ptr becomes empty, managing no object after the call.
unique_ptr objects automatically delete the object they manage (using a deleter) as soon as they themselves are destroyed, or as soon as their value changes either by an assignment operation or by an explicit call to unique_ptr::reset.
unique_ptr. An unique_ptr has exclusive ownership of the object it points to and will destroy the object when the pointer goes out of scope.
An explicit delete for a unique_ptr would be reset() . But do remember that unique_ptr are there so that you don't have to manage directly the memory they hold. That is, you should know that a unique_ptr will safely delete its underlying raw pointer once it goes out of scope.
The requirements of the call to the function object Deleter
are specific on this as listed in the requirements of the std::unique_ptr<T>::reset()
member.
From [unique.ptr.single.modifiers]/3, circa N4660 §23.11.1.2.5/3;
unique_ptr
modifiers
void reset(pointer p = pointer()) noexcept;
Requires: The expression
get_deleter()(get())
shall be well formed, shall have well-defined behavior, and shall not throw exceptions.
In general the type would need to be destructible. And as per the cppreference on the C++ concept Destructible, the standard lists this under the table in [utility.arg.requirements]/2, §20.5.3.1 (emphasis mine);
Destructible
requirements
u.~T()
All resources owned byu
are reclaimed, no exception is propagated.
Also note the general library requirements for replacement functions; [res.on.functions]/2.
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