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:

    1. Saves a copy of the current pointer old_ptr = current_ptr.
    2. Overwrites the current pointer with the argument current_ptr = ptr.
    3. 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.

有帮助吗?

解决方案

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 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 ]

(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.

其他提示

What if your deleter does not do a simple delete operation ? What if your unique_ptr has a custom deleter that does something else, would you like your deleter to be called with nullptr as a parameter ? :D

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top