我有一个定义如下的函数:
void foo(std::shared_ptr<X> x) { ... };
如果我将共享ptr声明为X
:
std::shared_ptr<X> sourcePtr(new X(...));
然后我可以按如下方式致电foo
:
foo(std::move(sourcePtr));
或
foo(sourcePtr);
我理解如果我使用第一个选项,那么sourcePtr
将变为空。它是否也会阻止引用计数递增?
如果这不重要,我应该选择哪个选项?做出这样的决定时,我应该考虑其他事情吗?
答案 0 :(得分:37)
是的,如果将共享指针移动到该函数中,则:
原始sourcePtr
将变为空,
引用计数不会被修改。
如果您知道在函数调用之后不再需要sourcePtr
的值,则将其移动到函数中是一种轻微的优化,因为它保存了原子增量(和当sourcePtr
超出范围时,后来减少。
但是,请注意标识符sourcePtr
对于作用域的其余部分仍然有效,只需保留空指针即可。这意味着如果您在移动后使用它,编译器将不会抱怨,但如果您忘记它被移动,您很可能取消引用null。我倾向于使用这个&#34;优化&#34; move
很多,而且我也被它咬了几次:函数中添加了更多功能,如果你忘记撤消move
,你会得到一个很好的崩溃。
当您不再需要它时,移动是轻微的优化,同时还有轻微的维护负担。在您的情况下,由您决定哪个更重要。
以上假设有一些代码在其声明和最终调用sourcePtr
之间实际使用foo
(感谢@WhozCraig指出它)。如果没有,那么你最好在呼叫站点创建指针
foo(std::make_shared<X>(...));
这样,您可以保存相同数量的原子操作,和您没有潜在危险的空共享指针。