提问者:小点点

为什么unique_ptr重载重置(指针p=指针())和重置(nullptr_t)?


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)给定current_ptr,由*this管理的指针,按以下顺序执行以下操作:保存当前指针的副本old_ptr=current_ptr;用参数覆盖当前指针current_ptr=ptr;如果旧指针非空,则删除先前管理的对象if(old_ptr!=nullptr)get_deleter()(old_ptr)

2)在动态数组的特化中,std::unique_ptr

3)在动态数组的特化中,std::unique_ptr

现在重置(nullptr)等价于重置(指针()),为什么存在后者?

如果我想重置数组形式unique_ptr,为什么我不能只使用rest(指针())


共2个答案

匿名用户

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

将被选择用于带有nullptr参数的调用,如果不是

void reset( std::nullptr_t p );

这就是它存在的原因,允许使用nullptr进行调用。

示例(使用定义的FIX编译以抑制编译错误):

#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.
}

匿名用户

重置ist实现为

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

针对数组删除模板化的重载,防止出现以下情况

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

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

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

这是未定义的行为。第5.3.5节第3段:

[…]在第二种选择(删除数组)中,如果要删除的对象的动态类型与其静态类型不同,则行为未定义。

由于已删除的函数仍然参与重载解析,并且重置(U)nullptr提供了比重置(指针)更好的匹配,因此存在允许重置(nullptr)的额外重载,否则将导致编译器错误,从而导致数组和指针版本之间的接口不一致。