简体   繁体   中英

Why does unique_ptr overload reset(pointer p = pointer()) and reset(nullptr_t)?

Accroding to http://en.cppreference.com/w/cpp/memory/unique_ptr/reset ,

void reset( pointer ptr = pointer() );

template< class U > 
void reset( U ) = delete;

void reset( std::nullptr_t p );

1) 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) .

2) In the specialization for dynamic arrays, std::unique_ptr<T[]> , this template member is provided to prevent using reset() with a pointer to derived (which would result in undefined behavior with arrays).

3) In the specialization for dynamic arrays, std::unique_ptr<T[]> , the third overload is necessary to allow reset to nullptr (which would otherwise be prohibited by the template overload). Equivalent to reset(pointer())

Now that reset(nullptr) is equivalent to reset(pointer()) , why does the latter exist?

If I want to reset an array form unique_ptr, why can I not just use rest(pointer()) ?

The

template< class U > 
void reset( U ) = delete;

would be chosen for a call with nullptr argument, if not for

void reset( std::nullptr_t p );

That's why it exists, to allow the call with nullptr .


Example (compile with FIX defined to suppress the compilation error):

#include <cstddef>      // std::nullptr_t

struct S
{
    void reset( char* ) {}

    template< class Type >
    void reset( Type ) = delete;

    #if FIX
    void reset( std::nullptr_t ) {}
    #endif
};

auto main() -> int
{
    S().reset( nullptr );    // Fails when FIX is not defined.
}

reset ist implemented as

pointer old = this->ptr;
this->ptr= newPointer;
delete[] old;

The templated overload is deleted for arrays to prevent the following case

class foo{};
class bar : public foo {};

foo* managedPointer = new foo[3];
bar* newPointer = new bar[5];

foo* old = managedPointer;
managedPointer = newPointer;
delete[] old;

Which is undefined behavior. Section 5.3.5 paragraph 3:

[...] In the second alternative (delete array) if the dynamic type of the object to be deleted differs from its static type, the behavior is undefined.

Since deleted functions still participate in overload resolution and reset(U) provide a better match for nullptr than reset(pointer) , there is an additional overload to to allow reset(nullptr) , which would otherwise give a compiler error and thus result in an inconsistent interface between array and pointer version.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM