C++ 使用std::move和std::shared\u ptr
我有一个定义如下的函数:C++ 使用std::move和std::shared\u ptr,c++,c++11,shared-ptr,move-semantics,C++,C++11,Shared Ptr,Move Semantics,我有一个定义如下的函数: void foo(std::shared_ptr<X> x) { ... }; foo(std::move(sourcePtr)); 然后我可以按如下方式调用foo: void foo(std::shared_ptr<X> x) { ... }; foo(std::move(sourcePtr)); 或 我知道如果我使用第一个选项,sourcePtr将变为空。它是否也阻止了引用计数的增加 如果这不重要,我应该选择哪个选项?在做出这样的决定
void foo(std::shared_ptr<X> x) { ... };
foo(std::move(sourcePtr));
然后我可以按如下方式调用foo
:
void foo(std::shared_ptr<X> x) { ... };
foo(std::move(sourcePtr));
或
我知道如果我使用第一个选项,sourcePtr
将变为空。它是否也阻止了引用计数的增加
如果这不重要,我应该选择哪个选项?在做出这样的决定时,我是否应该考虑其他事项?是的,如果将共享指针移动到函数中,则:
sourcePtr
将变为空,并且sourcePtr
的值,则将其移动到函数中是一个轻微的优化,因为它可以节省原子增量(以及以后sourcePtr
超出范围时的递减)
但是,请注意,标识符sourcePtr
对于作用域的其余部分仍然有效,只是它包含一个空指针。这意味着如果您在移动之后使用它,编译器不会抱怨,但是如果您忘记了它是从哪里移动的,那么很可能会取消对null的引用。我倾向于经常使用这种“优化”move
,我也曾被它咬过几次:更多的功能被添加到函数中,如果你忘记撤消move
,你会得到一个很好的崩溃
因此,当您不再需要移动时,这是一个轻微的优化,再加上轻微的维护负担。这取决于你权衡哪一个在你的情况下更重要
以上假设在声明和最后调用foo
之间存在实际使用sourcePtr
的代码(感谢@WhozCraig指出)。如果没有,最好在调用站点创建指针:
foo(std::make_shared<X>(...));
foo(std::make_shared(…);
这样,您可以保存相同数量的原子操作,并且不会有潜在危险的空共享指针。简言之,引用计数器不会增加,这是正确的。但是,我没有看到它的实际用途,除非您想强制将传递的指针清空,在这种情况下,您可以使用
std::unique_ptr
。您不应该将新的智能指针视为指针,而应该从资源所有权的角度来看待它们。一个资源只能由一个实体(std::unique\u ptr
)或多个实体(std::shared\u ptr
)拥有。这是一个非常类似的问题,尽管我不确定是否完全重复:。这个问题是关于将参数传递给函数的-以这种方式不同…@JoachimPileborg这是一些测试代码的简化示例,它并没有讲述整个故事,但允许我将问题专门集中在我想知道的内容上Foo
需要在我的应用程序中使用shared\u ptr
,但调用后测试代码不需要sourcePtr
。我认为这没有意义。这就是为什么引入了shared\u ptr
——这不仅是因为安全性(在避免内存泄漏方面),还因为复制对象的成本很高,可以(几乎)免费安全地共享。优化单个原子操作听起来像是浪费时间。为了我自己的澄清,如果创建和调用确实像示例一样简单(可能不是),那么就不会foo(std::make_shared(…)代码>在不放弃的情况下完成同样的事情(正如你所指出的,潜在的风险)std::shared\u ptr
shell?当然,如果在这两者(分配和调用)之间存在中间代码sourcePtr->member()
code,则这不是一个选项。但是如果没有呢?虽然我同意其他人的观点,这种优化违背了共享的目的,但这是我发现的第一篇讨论移动和复制指针的可维护性问题的文章(+1)。在许多情况下,由于不需要全局变量的原因,您不希望到处引用同一资源。如果您有动态绑定,您仍然需要指针,特别是unique\u ptr
。然后您必须使用move
(更多代码),但您可以更好地控制资源,并获得轻微的性能提升。