2014-09-19 78 views
1

傳遞shared_ptr<Derived>&作爲shared_ptr<Base>&時出現編譯錯誤,請參閱下面的代碼和詳細問題。傳遞shared_ptr時出錯<Derived>&as shared_ptr <Base>&without const

注意:此問題與「Passing shared_ptr<Derived> as shared_ptr<Base>」類似,但不重複。

#include <memory> 
class TBase 
{ 
public: 
    virtual ~TBase() {} 
}; 
class TDerived : public TBase 
{ 
public: 
    virtual ~TDerived() {} 
}; 
void FooRef(std::shared_ptr<TBase>& b) 
{ 
    // Do something 
} 

void FooConstRef(const std::shared_ptr<TBase>& b) 
{ 
    // Do something 
} 

void FooSharePtr(std::shared_ptr<TBase> b) 
{ 
    // Do something 
} 
int main() 
{ 
    std::shared_ptr<TDerived> d; 
    FooRef(d); // *1 Error: invalid initialization of reference of type ‘std::shared_ptr<TBase>&’ from expression of type ‘std::shared_ptr<TDerived>’ 
    FooConstRef(d); // *2 OK, just pass by const reference 
    FooSharePtr(d); // *3 OK, construct a new shared_ptr<> 
    return 0; 
} 

通過g++ -std=c++11 -o shared_ptr_pass_by_ref shared_ptr_pass_by_ref.cpp

的Env編譯:Ubuntu的14.04,克++(Ubuntu的4.8.2-19ubuntu1)4.8.2

詳細問題: 爲什麼行通過const引用傳遞(* 2),但不能通過引用(* 1)傳遞?

注:我知道最好的做法是通過const引用,但只是想知道爲什麼發生編譯錯誤。

+1

如果'FooRef'做了'b.reset(new TBase)'?如果可能的話,你最終會得到'std :: shared_ptr '擁有'TBase *'。順便說一句,我懷疑'FooConstRef'調用構造一個臨時的,然後綁定到const引用;但臨時表不能綁定到非const參考。 – 2014-09-19 02:57:01

+0

好點!我會接受這個答案 – Mine 2014-09-19 02:59:09

回答

3

您似乎期望某種模板協方差,因此AnyTemplateClass<Derived>可以綁定到AnyTemplateClass<Base>&。模板不以這種方式工作。通常,AnyTemplateClass<Derived>AnyTemplateClass<Base>是兩個截然不同的完全不相關的類。

一個特定的模板類可以或者當然以某種形式提供關係。 shared_ptr<T>特別具有模板化的構造函數,接受shared_ptr<U>用於任何U,使得U*可以轉換爲T*

FooConstRef(d)調用工作通過構建一個臨時的 - 有效

shared_ptr<TBase> temp(d); 
FooConstRef(temp); 

但臨時對象不能綁定到非const引用,這就是爲什麼FooRef(d)不以類似的方式工作。

+0

很好的答案!但還有一個問題,爲什麼可以有效地創建'shared_ptr '的臨時** **?只要它是一個新的'shared_ptr',它仍然會增加'use_count'。那麼,如果我們總是通過shared_ptr ,那麼'FooConstRef()'和'FooSharePtr()'之間是否存在任何性能差異? – Mine 2014-09-19 03:18:06

+0

「有效」!=「有效」。鑑於這個事實,我不確定我是否理解你的問題。你在我的發言中似乎假設我沒有放在那裏。 – 2014-09-19 05:29:53

+0

對不清楚的問題,讓我重新說一句:如果傳遞的參數是'shared_ptr ',那麼'FooConstRef()'和'FooSharePtr()'之間是否存在任何性能差異?如果我理解正確,它們具有相同的行爲,因爲兩者都構造了一個臨時'shared_ptr ',對吧? – Mine 2014-09-19 07:55:30