使用 std::move 和 std::shared_ptr

Using std::move with std::shared_ptr

我有一个函数定义如下:

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

如果我声明一个指向 X 的共享指针:

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

然后我可以按如下方式调用 foo

foo(std::move(sourcePtr));

foo(sourcePtr);

我知道如果我使用第一个选项,那么 sourcePtr 将变为空。它是否也阻止了引用计数的增加?

如果那不重要,我应该更喜欢哪个选项?在做出这样的决定时,我是否应该考虑其他因素?

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

  1. 原来的sourcePtr会变成null,而

  2. 引用计数没有被修改。

如果您知道在函数调用后您将不再需要 sourcePtr 的值,将其移动到函数中是一个轻微的优化,因为它节省了 atomic 递增(然后递减,当 sourcePtr 超出范围时)。

但是,请注意标识符 sourcePtr 对范围的其余部分仍然有效,只是它包含一个空指针。这意味着如果您在移动后使用它,编译器不会抱怨,但如果您忘记它是从哪里移动的,您很可能会取消引用 null。这个"optimising"move我比较常用,我也被它咬过几次:功能多加了功能,如果忘了撤消move, 你得到一个很好的崩溃。

所以当您不再需要它时移动它是一种轻微的优化加上轻微的维护负担。哪个更重要取决于您的情况。

以上假定在其声明和最终调用 foo 之间存在实际使用 sourcePtr 的代码(感谢@WhozCraig 指出)。如果没有,您最好 在调用站点创建指针:

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

这样,您节省了相同数量的原子操作,并且您没有潜在危险的空共享指针。