Using std::move with std::shared_ptr

Using std::move with std::shared_ptr

本文关键字:std shared ptr move Using with      更新时间:2023-10-16

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

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

如果我向X:声明共享ptr

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

然后我可以如下调用foo

foo(std::move(sourcePtr));

foo(sourcePtr);

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

如果没关系,我应该选择哪一种?在做出这样的决定时,我应该考虑其他事情吗?

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

  1. 原始sourcePtr将变为空,并且

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

如果您知道在函数调用后将不再需要sourcePtr的值,那么将其移动到函数中是一个轻微的优化,因为它保存了原子增量(以及稍后的减量,当sourcePtr超出范围时)。

但是,请注意,标识符sourcePtr对于作用域的其余部分仍然有效,只是它包含一个空指针。这意味着,如果你在移动后使用它,编译器不会抱怨,但如果你忘记了它是从中移动的,你很可能会取消引用null。我倾向于经常使用这种"优化"move,我也被它咬过几次:函数中添加了更多的功能,如果你忘记撤消move,你会崩溃。

因此,当您不再需要移动时,这是一个轻微的优化,再加上轻微的维护负担。在你的情况下,哪个更重要,由你来衡量。

上面假设在声明和对foo的最终调用之间有一段代码实际上使用了sourcePtr(感谢@WhozCraig指出了这一点)。如果没有,你最好在调用站点创建指针:

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

通过这种方式,您可以节省相同数量的原子操作,您不会有潜在危险的空共享指针。