【问题标题】:理解带有右值函数调用的 shared_ptr 的移动语义
【发布时间】:2022-01-23 14:12:17
【问题描述】:

在下面的小程序中我有两个使用moveshared_ptr的例子。

第一个示例的行为符合我的预期,shared_ptr p 的所有权分配给新指针 p2。赋值后p 是无效指针。

我希望在第二个示例中也会发生同样的情况,但事实并非如此。精确的问题作为 cmets 嵌入到源代码中。我的推理有什么问题?

#include <memory>
#include <iostream>
using namespace std;

void foo(shared_ptr<int>&& p)
{
    std::cout << "zoo: " << p.use_count() << "\n";
    // when this function terminates, should the destructor of p
    // decrement the ref counter and destroy the pointed object?
}

void example1()
{
    auto p = make_shared<int>(0);
    std::cout << "count before move: " << p.use_count() << "\n";
    shared_ptr<int> p2(move(p));
    std::cout << "count after move: " << p.use_count() << "\n";  // output 0: ownership transferred to p2
}

void example2()
{
    auto p = make_shared<int>(0);
    std::cout << "count before move: " << p.use_count() << "\n";
    foo(move(p));
    std::cout << "count after move: " << p.use_count() << "\n";
    // output 1: Why is this not zero?
    //Why has ownership not transferred to the argument of the function foo? 
}

int main()
{
    example1();
    example2();
    return 0;
}

【问题讨论】:

  • std::move() 并不是真正的移动——它实际上是一个右值引用转换。 foo() 的参数 p 不会在 foo() 中的任何位置移动。因此,它保留在p。如果您在foo() 中添加您的p2 行,您将达到您想要的效果:Demo on coliru
  • std::move 表示“您可以移动此对象”。这并不意味着对象被占用,只是它可能被占用。该示例的foo 例程不采用允许移动的对象。

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


【解决方案1】:

为什么所有权没有转移到函数 foo 的参数上?

因为foo的参数类型是shared_ptr右值引用,所以没有创建新的shared_ptr对象,foo中的p只是一个对原始 p 的引用,它没有移动到任何对象。

如果你把foo改成传值,就会创建一个新的shared_ptr对象,那么你会发现p已经被移动了:

void foo(shared_ptr<int> p)
{
    //...
}
foo(move(p)); // ownership transferred

【讨论】:

    猜你喜欢
    • 2021-09-24
    • 2012-12-10
    • 2013-02-14
    • 2020-10-03
    • 1970-01-01
    • 2019-07-22
    • 1970-01-01
    • 2017-09-15
    • 1970-01-01
    相关资源
    最近更新 更多