通过右值函数调用理解 shared_ptr 的移动语义

understanding move semantic for a shared_ptr with an rvalue function call

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

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

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

#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;
}

Why has ownership not transferred to the argument of the function foo?

因为foo的参数类型是shared_ptr右值引用,没有创建新的shared_ptr对象,[= foo 中的 14=] 只是对原始 p 引用 移动到任何对象。

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

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