2011-08-12 41 views
4

以下的weak_ptr的構造函數的是2: http://msdn.microsoft.com/en-us/library/bb982126.aspx的weak_ptr的怪異的拷貝構造函數

weak_ptr(const weak_ptr&); 

template<class Other> 
weak_ptr(const weak_ptr<Other>&); 

實際代碼(從memory):

weak_ptr(const weak_ptr& _Other) 
{ // construct weak_ptr object for resource pointed to by _Other 
    this->_Resetw(_Other); 
} 

template<class _Ty2> 
weak_ptr(const weak_ptr<_Ty2>& _Other, 
     typename enable_if<is_convertible<_Ty2 *, _Ty *>::value, 
     void *>::type * = 0) 
{ // construct weak_ptr object for resource pointed to by _Other 
    this->_Resetw(_Other); 
} 

Q1:爲什麼是頂級的拷貝構造函數,甚至有?它看起來像是每個案例的最底層(包括最高層)。它甚至被稱爲?如果他們沒有包括它,底部的一個會佔據它的位置? Q2:底層(模板化)構造函數的第二個參數是怎麼回事。我想我理解SFINAE方面,但我不明白爲什麼有一個額外的*之後::type

+0

@Hans,那麼爲什麼不固定的縮進? – Motti

回答

5

Q1)如果你不寫一個拷貝構造函數,編譯器會爲你生成一個,成爲你想成爲的人。模板化的轉換構造函數不計數。

Q2)請記住,shared_ptr<T>就像是T*,必須在指針級別檢查可轉換性。如果T*可轉換爲U*那麼您應該可以將一個指派給另一個。想想指向基地的指針。 [抱歉,這不是你問的。]最後一個參數類型只是需要存在,但我們也不想指定參數本身。構成一種我們也可以提供缺省參數的類型的通用方法是一個指針。簡而言之,我們需要使該功能取決於可能存在或不存在的類型,但實際上並不需要用戶知道這一點。

+1

如果'*'在'= 0'之前不存在,它仍然是成功的void *類型。是不是額外的*使它成爲一個無效的**,但爲什麼他們不會在這種情況下寫void *而不是void *? 此外,他們爲什麼不寫0 nullptr,是一個錯誤? – David

+1

@Dave:你不*有*使用'nullptr',這只是一個可選的新功能。無論如何,我不確定爲什麼你需要一個雙指針實際上,也許只是他們的房子風格總是使用SFINAE通過指針,而他們恰好在這種情況下使用'void *'作爲內部類型。 GCC不會通過函數參數完成此操作,而是使用默認模板參數以零運行時代價觸發替換失敗。 –

+2

LOL。我剛剛寫了一個基於_Ptr_Base的weak_ptr類似的東西,如果我們所談論的第二個'*'不存在VS說... '錯誤錯誤C1001:編譯器中發生內部錯誤。 所以,這就是爲什麼它在那裏。哈。 – David

3

Re Q1:模板化的構造函數從來不是「拷貝構造函數」,即使它能夠複製。如果沒有用戶定義的「拷貝構造函數」,那麼編譯器將根據需要生成一個。

Re Q2:第二個參數,默認爲0的指針,只是有一個地方把enable_if。你可以在Boost文檔中找到更多關於(如果我記得正確的話)。

乾杯&心連心,