我应该通过引用传递 share_ptr 吗?

传递 share _ ptr 的最佳实践是什么?

目前我传递 share _ ptr 函数参数的方式如下:

void function1( shared_ptr<TYPE>& value );
120318 次浏览

在受控的情况下,可以通过 恒定参考传递共享指针。确保没有人同时删除对象,但是如果您注意提供引用的对象,那么这应该不会太难。

通常,应该将共享指针作为直接 收到传递。这赋予了它预期的语义: 包含共享指针副本的每个作用域通过其在所有权中的“共享”使对象保持活动。

不总是通过值传递的唯一原因是,由于原子引用计数更新,复制共享指针需要付出一定的代价; 然而,这可能不是一个主要问题。


可选题外话:

既然主要问题已经得到了回答,那么考虑一下 永远不会使用共享指针的几种方式也许是有益的。这是一个小小的思想实验。让我们定义一个共享指针类型 SF = std::shared_ptr<Foo>。为了考虑引用,让我们看看类型 RSF = std::reference_wrapper<T>,而不是传递函数参数。也就是说,如果我们有一个共享的指针 SF p(std::make_shared<Foo>());,那么我们可以通过 RSF w = std::ref(p);创建一个具有值语义的引用包装器。布置到此为止。

大家都知道装指针的容器是雷区。因此,维护 std::vector<Foo*>将是一场噩梦,任何数量的错误都可能源自不适当的生命周期管理。在概念上更糟糕的是,从来不清楚谁是 拥有,谁是容器存储指针的对象。指针甚至可以是指向动态对象、自动对象和垃圾的混合指针。没人知道。因此,标准的解决方案是使用 std::vector<SF>代替。这是使用共享指针的正确方法。另一方面,绝对不能使用的是 std::vector<RSF>——这是一个难以管理的怪物,实际上与原来的裸指针向量非常相似!例如,不清楚保存引用的对象是否仍然活着。获取共享指针的引用已经完全失败了。

对于第二个示例,假设我们像前面一样有一个共享指针 SF p。现在我们有一个要并发运行的函数 int foo(SF)。通常的 std::thread(foo, p)工作得很好,因为线程构造函数使其参数成为 收到。但是,如果我们说的是 std::thread(foo, std::ref(p)),我们就会遇到各种各样的麻烦: 调用范围中的共享指针可能会过期并破坏对象,而且您将留下一个悬空的引用和一个无效的指针!

我希望这两个公认的人为设计的示例能够帮助您了解什么时候真正希望通过 收到传递共享指针。在一个设计良好的程序中,应该始终清楚谁对哪些资源负责,如果使用得当,共享指针是一个很好的工具。

如果通过引用传递,则通过常量引用传递。这说明你是因为表现的原因而错过了裁判。另外,尽可能使用 make _ share,因为它可以保存间接性,从而提高性能。

这取决于你想要什么。被调用方是否应该共享对象的所有权?然后,它需要自己的 shared_ptr副本。按值传递。

如果函数只是需要访问调用者拥有的对象,那么继续并通过(const)引用传递,以避免复制 shared_ptr的开销。

C + + 中的最佳实践是 一直都是,它为您的对象具有明确定义的所有权语义。没有普遍的“总是这样做”来取代实际的 思考

如果通过值传递共享指针,则代价会很高(因为它们复制起来比原始指针昂贵得多)。如果您使用 永远不会,那么一开始就没有必要使用共享指针。

当新函数或对象需要共享指针的所有权时,复制共享指针。