传递共享指针作为参数
如果我声明一个包装在共享指针中的对象:
std::shared_ptr<myClass> myClassObject(new myClass());
那么我想把它作为一个parameter passing给一个方法:
DoSomething(myClassObject); //the called method void DoSomething(std::shared_ptr<myClass> arg1) { arg1->someField = 4; }
以上是否简单地增加了shared_pt的引用计数,一切都很酷? 还是会留下一个晃来晃去的指针?
你还是应该这样做吗?
DoSomething(myClassObject.Get()); void DoSomething(std::shared_ptr<myClass>* arg1) { (*arg1)->someField = 4; }
我认为第二种方法可能更有效率,因为它只需要复制1个地址(而不是整个智能指针),但是第一种方式看起来更具可读性,我不希望推行性能限制。 我只是想确保没有什么危险的事情。
谢谢。
我想传递一个函数的共享指针。 你能帮我吗?
当然,我可以帮你。 我假设你对C ++中的所有权语义有一些了解。 真的吗?
是的,我对这个问题很合适。
好。
好吧,我只能想到采取shared_ptr
参数的两个理由:
- 该function要分享对象的所有权;
- 该函数执行一些专门在
shared_ptr
的操作。
你对哪一个感兴趣?
我正在寻找一个普遍的答案,所以我实际上对两个都感兴趣。 不过,我很好奇你的意思。
这样的函数的例子包括std::static_pointer_cast
,自定义比较器或谓词。 例如,如果您需要从vector中find所有唯一的shared_ptr,则需要这样的谓词。
啊,这个函数实际上需要操纵智能指针本身。
究竟。
在这种情况下,我认为我们应该通过参考。
是。 如果它不改变指针,你想通过const引用传递。 没有必要复制,因为你不需要共享所有权。 这是另一种情况。
好的,我知道了。 我们来谈谈另一种情况。
你分享所有权的那个? 好。 你如何与shared_ptr
共享所有权?
通过复制它。
那么这个函数需要复制一个shared_ptr
,是否正确?
明显。 所以我通过引用const传递它并复制到一个局部variables?
不,这是一个悲观。 如果通过引用传递,则该function将别无select,只能手动进行复制。 如果按值传递,编译器会select副本和移动之间的最佳select并自动执行。 所以,按价值传递。
好点子。 我必须记得更多的时候是“ 想要速度?超值 ”。
等等,如果函数将
shared_ptr
存储在成员variables中,例如? 这不会造成多余的副本吗?
该函数可以简单地将shared_ptr
参数移动到其存储中。 移动一个shared_ptr
是很便宜的,因为它不会改变任何引用计数。
啊,好主意。
但是我想到了第三种情况:如果你不想操纵
shared_ptr
,又不想共享所有权呢?
在这种情况下, shared_ptr
与函数完全无关。 如果你想操纵指针,拿指尖,让调用者select他们想要的所有权语义。
我应该参照还是通过价值来指责?
通常的规则适用。 智能指针不会改变任何东西。
如果我要复制,按照价值传递,如果我想避免复制,请按照参考传递。
对。
嗯。 我想你忘了另一个场景。 如果我想分享所有权,但仅仅依赖于某种条件呢?
啊,一个有趣的边缘情况。 我不期望经常发生。 但是当它发生的时候,你可以通过价值传递,如果你不需要,可以忽略副本,或者通过引用传递,如果你需要的话可以复制。
第一个选项我冒了一个多余的副本,并在第二个选项中失去了一个潜在的举措。 我不能吃这个蛋糕吗?
如果你处于一个非常重要的情况,你可以提供两个重载,一个取const Lvalue引用,另一个取右值引用。 一个副本,另一个副本。 完美转发function模板是另一种select。
我认为这涵盖了所有可能的情况。 非常感谢你。
我认为人们不必要地害怕使用原始指针作为函数参数。 如果函数不会存储指针或影响其生存期,则原始指针也可以正常工作,并表示最小公分母。 例如,考虑如何将unique_ptr
传递unique_ptr
shared_ptr
作为参数的函数,无论是通过值还是通过const引用?
void DoSomething(myClass * p); DoSomething(myClass_shared_ptr.get()); DoSomething(myClass_unique_ptr.get());
作为函数参数的原始指针不会阻止您在调用代码中使用智能指针,而这些指针真的很重要。
是的,关于shared_ptr <>的整个想法是多个实例可以保存相同的原始指针,并且只有在shared_ptr <>的最后一个实例被销毁时才会释放底层内存。
我会避免一个指向shared_ptr <>的指针,因为这是你正在处理的raw_pointers再次失败的目的。
在你的第一个例子中传递值是安全的,但有一个更好的习惯用法。 尽可能传递const引用 – 即使在处理智能指针时,我也会说是。 你的第二个例子不是完全破碎,但它是非常!???
。 愚蠢的是,没有完成任何事情,击败了智能指针的一部分,当你试图解引用和修改东西时,会让你陷入一个错误的痛苦世界。