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

时间:2014-06-23 05:53:38

标签: c++ arrays c++11 overloading unique-ptr

正在加载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<T[]>,   提供此模板成员是为了防止将reset()用于   指向派生的指针(这将导致未定义的行为   阵列)。

     

3)在动态数组的专门化中,std::unique_ptr<T[]>,   第三次重载是必要的,以允许重置为nullptr(这将是   否则被模板超载禁止)。相当于   reset(pointer())

现在reset(nullptr)等同于reset(pointer()),为什么后者存在?

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

2 个答案:

答案 0 :(得分:7)

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

答案 1 :(得分:2)

reset实现为

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段:

  

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

由于已删除的功能仍然参与重载决策,reset(U)提供的nullptrreset(pointer)的匹配度更高 ,允许reset(nullptr)有一个额外的重载,否则会产生编译器错误,从而导致数组和指针版本之间的接口不一致。