Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is std::unique_ptr::reset() always noexcept?

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)?

like image 587
anderas Avatar asked Feb 19 '18 07:02

anderas


People also ask

What does unique_ptr Reset do?

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.

Does unique_ptr call Delete?

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.

What happens when unique_ptr goes out of scope?

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.

How do you destroy a unique pointer?

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.


1 Answers

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 by u are reclaimed, no exception is propagated.

Also note the general library requirements for replacement functions; [res.on.functions]/2.

like image 64
Niall Avatar answered Oct 05 '22 22:10

Niall