路过的shared_ptr 作为shared_ptr的 路过的shared_ptr 作为

2019-05-12 23:22发布

什么是去传递一个最好的方法shared_ptr派生类型的给带有一个功能shared_ptr基本类型的?

我一般通过shared_ptr S按参考,以避免不必要的副本:

int foo(const shared_ptr<bar>& ptr);

但如果我尝试做这样的事情不工作

int foo(const shared_ptr<Base>& ptr);

...

shared_ptr<Derived> bar = make_shared<Derived>();
foo(bar);

我可以用

foo(dynamic_pointer_cast<Base, Derived>(bar));

但是这似乎次优的,原因有二:

  • 一个dynamic_cast似乎是一个简单的导出到基础施法有点过分。
  • 据我了解, dynamic_pointer_cast创建指针的副本(尽管是暂时的)传递给函数。

有没有更好的解决办法?

更新为后人:

它原来是一个缺少的头文件的问题。 此外,我试图在这里做被认为是一个反模式。 通常,

  • 不影响的对象的生存期的功能(即,对象仍然有效的函数的持续时间)应该采取纯引用或指针,例如int foo(bar& b)

  • 消耗对象的函数(即,在给定对象的最终用户)应该采取unique_ptr由值,例如int foo(unique_ptr<bar> b) 调用者应该std::move值到函数。

  • 延伸的对象的生命周期功能应该采取shared_ptr由值,例如int foo(shared_ptr<bar> b) 通常的建议,以避免循环引用适用。

见香草萨特的歌姬交谈了解详情。

Answer 1:

虽然BaseDerived是协变和原始指针到他们将相应地动作, shared_ptr<Base>shared_ptr<Derived> 不是协变。 该dynamic_pointer_cast是处理这个问题的正确和最简单的方法。

编辑: static_pointer_cast因为你来源于基地,这是安全的,不需要运行时检查铸件会更合适,请参阅下面的评论。)

但是,如果您foo()函数不希望参加延长寿命(或者说,参加对象的共享所有权的一部分),那么它的最好接受const Base&和取消引用shared_ptr传递时,到foo()

void foo(const Base& base);
[...]
shared_ptr<Derived> spDerived = getDerived();
foo(*spDerived);

顺便说一句,因为shared_ptr类型不能协变,横跨协变返回类型的隐式转换的规则不返回类型时,适用shared_ptr<T>



Answer 2:

听起来像是你想太硬。 shared_ptr是廉价的复制; 这就是目标之一。 参照各地传递他们并没有真正大有作为。 如果你不想做的共享,通过原始指针。

这就是说,有两种方法可以做到这一点,我能想到的把我的头顶部:

foo(shared_ptr<Base>(bar));
foo(static_pointer_cast<Base>(bar));


Answer 3:

此外,检查#include包含派生类的完整声明的头文件是在源文件中。

我有这个问题。 所述std::shared<derived>不会投射到std::shared<base> 。 我前宣布这两个类,这样我可以抱球给他们,而是因为我没有足够的#include编译器无法看到,一类是从其他的。



Answer 4:

这也将发生,如果你忘了在派生类中指定公有继承,如果你像我写这篇文章,即:

class Derived : Base
{
};


文章来源: Passing shared_ptr as shared_ptr