我应该通过引用传递一个shared_ptr?
传递shared_ptr的最佳实践是什么?
目前我通过shared_ptr函数参数如下所示:
void function1( shared_ptr<TYPE>& value );
在受控制的情况下,您可以通过常量引用传递共享指针。 确保没有人同时删除这个对象,但是如果你仔细地向谁提供引用,这应该不会太难。
通常,您应该将共享指针作为直接副本传递。 这给了它预期的语义:每个包含共享指针副本的作用域都依靠所有权中的“共享”使对象保持活动状态。
不总是按值传递的唯一原因是,由于primefaces引用计数更新,复制共享指针的价格是一定的; 不过,这可能不是一个主要的问题。
可选题外话:
由于主要问题已经得到解答,所以考虑一些不应该使用共享指针的方法可能是有益的。 这是一个小小的想法实验。 让我们定义一个共享指针typesSF = std::shared_ptr<Foo>
。 为了考虑引用,而不是传递函数参数,让我们看看typesRSF = std::reference_wrapper<T>
。 也就是说,如果我们有一个共享指针SF p(std::make_shared<Foo>());
,那么我们可以通过RSF w = std::ref(p);
做一个带有值语义的引用包装RSF w = std::ref(p);
。 这么多的设置。
现在,大家都知道指针的容器是雷区。 所以std::vector<Foo*>
将是一个噩梦来维护,并且任何数量的错误都是由不适当的生命周期pipe理引起的。 在概念上更糟糕的是,谁拥有容器存储指针的对象是不清楚的。 指针甚至可以是指向dynamic对象,自动对象和垃圾的指针的混合。 没有人能说出来。 所以标准的解决scheme是使用std::vector<SF>
来代替。 这是使用共享指针的正确方法。 另一方面,你绝对不能使用的是std::vector<RSF>
– 这是一个难以pipe理的怪物,它实际上与裸指针的原始vector非常相似! 例如,您所持有的引用对象是否仍然存在尚不清楚。 参考共享指针已经失败了它的全部目的。
对于第二个例子,假设我们有一个像前面一样的共享指针SF p
。 现在我们有一个函数int foo(SF)
,我们想同时运行。 通常的std::thread(foo, p)
工作得很好,因为线程构造函数复制了它的参数。 但是,如果我们说std::thread(foo, std::ref(p))
,我们会遇到各种各样的麻烦:调用范围中的共享指针可能会过期并销毁该对象,有一个悬而未决的参考和一个无效的指针!
我希望这两个公认的相当人为的例子在你真的希望你的共享指针被拷贝传递的时候有一点点亮。 在一个精心devise的程序中,应该始终明确由谁来负责哪些资源,如果使用得当,共享指针是工作的重要工具。
这取决于你想要什么。 被调用者是否应共享该对象的所有权? 然后它需要自己的shared_ptr
副本。 所以通过价值传递。
如果一个函数只需要访问调用者拥有的对象,那么继续传递(const)引用,以避免复制shared_ptr
的开销。
C ++中的最佳实践始终是为您的对象明确定义所有权语义。 没有普遍的“总是这样”取代实际的思想 。
如果你总是按值传递共享指针,那么代价是昂贵的(因为它们比原始指针要昂贵得多)。 如果你从来不这样做,那么首先使用共享指针就没有意义了。
当新函数或对象需要共享指针对象的所有权时,复制共享指针。
如果通过引用传递,则通过const引用传递它。 这表明你出于性能考虑而通过ref。 另外,可以使用make_shared,因为它节省了一个间接的时间,所以给出了一个perf的提升。