2014-09-19 83 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