使用std :: move与std :: shared_ptr

时间:2015-04-15 07:21:57

标签: c++ c++11 shared-ptr move-semantics

我有一个定义如下的函数:

void foo(std::shared_ptr<X> x) { ... };

如果我将共享ptr声明为X

std::shared_ptr<X> sourcePtr(new X(...));

然后我可以按如下方式致电foo

foo(std::move(sourcePtr));

foo(sourcePtr);

我理解如果我使用第一个选项,那么sourcePtr将变为空。它是否也会阻止引用计数递增?

如果这不重要,我应该选择哪个选项?做出这样的决定时,我应该考虑其他事情吗?

1 个答案:

答案 0 :(得分:37)

是的,如果将共享指针移动到该函数中,则:

  1. 原始sourcePtr将变为空,

  2. 引用计数不会被修改。

  3. 如果您知道在函数调用之后不再需要sourcePtr的值,则将其移动到函数中是一种轻微的优化,因为它保存了原子增量(和当sourcePtr超出范围时,后来减少。

    但是,请注意标识符sourcePtr对于作用域的其余部分仍然有效,只需保留空指针即可。这意味着如果您在移动后使用它,编译器将不会抱怨,但如果您忘记它被移动,您很可能取消引用null。我倾向于使用这个&#34;优化&#34; move很多,而且我也被它咬了几次:函数中添加了更多功能,如果你忘记撤消move,你会得到一个很好的崩溃。

    当您不再需要它时,移动是轻微的优化,同时还有轻微的维护负担。在您的情况下,由您决定哪个更重要。

    以上假设有一些代码在其声明和最终调用sourcePtr之间实际使用foo(感谢@WhozCraig指出它)。如果没有,那么你最好在呼叫站点创建指针

    foo(std::make_shared<X>(...));
    

    这样,您可以保存相同数量的原子操作,您没有潜在危险的空共享指针。