I've been reading about the C++11 smart pointers in order to use them on my sources, the documentation I've been reading is the one on cppreference.com; while reading about the std::unique_ptr
, on the reset
function there's a documentation that seems incorrect to me (emphasis mine):
Replaces the managed object.
Given
current_ptr
, the pointer that was managed by*this
, performs the following actions, in this order:
- Saves a copy of the current pointer
old_ptr = current_ptr
.- Overwrites the current pointer with the argument
current_ptr = ptr
.- If the old pointer was non-empty, deletes the previously managed object
if(old_ptr != nullptr) get_deleter()(old_ptr)
.
In the C++ standard documentation, we can read the well known delete null pointer feature:
Extract from n3690
standard 5.3.5 Delete (emphasis mine):
If the value of the operand of the delete-expression is not a null pointer value, then:
— If the allocation call for the new-expression for the object to be deleted was not omitted, the delete-expression shall call a deallocation function. The value returned from the allocation call of the new-expression shall be passed as the first argument to the deallocation function.
— Otherwise, the delete-expression will not call a deallocation function.
So, I'm wondering why cppreference says that the unique_ptr::reset
function checks for the nullity of the managed pointer before it's deletion even while te standard says that no deallocation function would be called over a null pointer (that's why the cppreference documentation seems incorrect to me).
Is kind of obvious that I must be mistaken and there must be a reason to do things this way, but I'm unable to imagine what reason it could be. Any hints?
PS: Where in the standard is defined how the std::unique_ptr
must be implemented or behave? In the 20.9.1 Class template unique_ptr
I cannot found anything about the check-for-nullity stuff.
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.
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.
std::unique_ptr is a smart pointer that owns and manages another object through a pointer and disposes of that object when the unique_ptr goes out of scope. The object is disposed of, using the associated deleter when either of the following happens: the managing unique_ptr object is destroyed.
Yes, the check for non-null is required by the standard (C++11, [unique.ptr.single.modifiers]§4
):
void reset(pointer p = pointer()) noexcept;
4 Effects: assigns
p
to 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 to get_deleter() may destroy*this
. —end note ]
(emphasis mine)
Discussion: An alternative way to standardise it would be to put the "burden" on the user of the class, i.e. require all deleters (the default one and any custom ones) to work fine when invoked on a null pointer.
However, I understand the idea was to enable functions like free()
and even things like a hypothetical unlock_mutex(Mutex*)
to work as deleters out-of-the-box, regardless of how/if they handle null pointers. So putting this check into the unique_ptr
itself broadens the selection of deleters which can be used directly.
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