2014-06-23 34 views
3

Accroding到http://en.cppreference.com/w/cpp/memory/unique_ptr/reset爲什麼unique_ptr過載重置(指針p = pointer())和reset(nullptr_t)?

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

+1

我真正找到方法'delete'ion更有趣...... – Mehrdad

+4

因爲這將是愚蠢的有'p.reset(nullptr)'是一個編譯錯誤? –

+2

請注意'std :: unique_ptr '只接受'T *'和'T *'作爲其構造函數和'reset'方法的指針類型。值得注意的是,即使它們可以轉換爲指向T的**,它也不接受指向與T不同的類型的指針。換句話說:沒有那個重載'p.reset(nullptr);'不會編譯。這將是非常愚蠢的。 (出於同樣的原因,有'unique_ptr(nullptr_t)'ctor。) – peppe

回答

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

爲什麼重置(nullptr)無法解析爲重置(指針)? #1表格比#2表格更具體。所以,我認爲,即使沒有#3表格,超載分辨率仍然可以工作。 – xmllmx

+6

@xmllmx:模板在類型上完全匹配,而非模板涉及轉換。 –

2

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

[...]在第二個替代方案(刪除數組)中,如果要刪除的對象的動態類型與其靜態類型不同,則行爲是未定義的。

由於刪除的功能仍然參與重載分辨率和reset(U)提供nullptr更好的匹配比reset(pointer) ,有一個附加的過載,以允許reset(nullptr),否則給編譯錯誤,從而導致不一致的接口數組和指針版本之間。