【问题标题】:Error passing shared_ptr<Derived>& as shared_ptr<Base>& without const在没有 const 的情况下将 shared_ptr<Derived>& 作为 shared_ptr<Base>& 传递时出错
【发布时间】:2014-09-19 02:54:40
【问题描述】:

shared_ptr&lt;Derived&gt;&amp; 传递为shared_ptr&lt;Base&gt;&amp; 时出现编译错误,请参阅下面的代码和详细问题。

注意:此问题与“Passing shared_ptr&lt;Derived&gt; as shared_ptr&lt;Base&gt;”类似,但不重复。

#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编译

环境:Ubuntu 14.04,g++ (Ubuntu 4.8.2-19ubuntu1) 4.8.2

详细问题: 为什么通过 const 引用(*2)可以传递,但不能通过引用(*1)传递?

注意:我知道最好的做法是通过 const 引用传递,但只是想知道为什么会出现编译错误。

【问题讨论】:

  • 如果FooRefb.reset(new TBase) 怎么办?如果可以调用,您最终会得到std::shared_ptr&lt;TDerived&gt; 持有TBase*。顺便说一句,我怀疑 FooConstRef 调用构造了一个临时的,然后绑定到 const 引用;但是临时对象不能绑定到非常量引用。
  • 好点!我会接受这个答案

标签: c++ inheritance c++11 casting shared-ptr


【解决方案1】:

您似乎期望某种模板协方差,从而AnyTemplateClass&lt;Derived&gt; 可以绑定到AnyTemplateClass&lt;Base&gt;&amp;。模板不能以这种方式工作。通常,AnyTemplateClass&lt;Derived&gt;AnyTemplateClass&lt;Base&gt; 是两个截然不同的、完全不相关的类。

一个特定的模板类可能,或者当然,提供某种形式的关系。 shared_ptr&lt;T&gt; 特别有一个模板化的构造函数,它接受任何 Ushared_ptr&lt;U&gt;,这样 U* 可以转换为 T*

FooConstRef(d) 调用通过构造一个临时的 - 有效地工作

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

但是临时对象不能绑定到非常量引用,这就是为什么FooRef(d) 不能以类似的方式工作。

【讨论】:

  • 很好的答案!但是还有一个问题,为什么可以有效地创建shared_ptr&lt;TBase&gt;的临时地址?只要是新的shared_ptr,它仍然会增加use_count。那么FooConstRef()FooSharePtr()之间有什么性能差异,如果我们总是通过shared_ptr
  • “有效地”!=“有效地”。鉴于这一事实,我不确定我是否完全理解你的问题。你似乎在我的陈述中假设了一些我没有在那里表达的意思。
  • 对不起,问题不清楚,让我重新表述一下:如果传递的参数是shared_ptr&lt;TDerived&gt;FooConstRef()FooSharePtr() 之间是否有任何性能差异?如果我理解正确的话,它们的行为是一样的,因为它们都构造了一个临时的shared_ptr&lt;TBase&gt;,对吧?
  • 不,我认为在给定的限制下没有任何区别。
猜你喜欢
  • 2012-11-04
  • 1970-01-01
  • 2017-08-06
  • 2010-11-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-21
相关资源
最近更新 更多