在C++中使用std::unique_ptr理解std::move和所有权转移

ao218c7q  于 2023-07-01  发布在  其他
关注(0)|答案(2)|浏览(223)

我写了两组函数,F1/test1和F2/test 2,我试图理解这些函数中std::move的行为和std::unique_ptr的所有权转移的区别。下面是代码:

void F1(std::unique_ptr<Dog>&& uPtr)
{
    std::cout << "F1 \n";
}

void test1()
{
    std::unique_ptr<Dog> pD(new Dog("Gunner"));
    F1(std::move(pD));
    if (pD == nullptr)
    {
        std::cout << "Null\n";
    }
    std::cout << "Test \n";
}

void F2(std::unique_ptr<Dog> uPtr)
{
    std::cout << "F2 \n";
}

void test2()
{
    std::unique_ptr<Dog> pD(new Dog("Smokey"));
    F2(std::move(pD));
    if (pD == nullptr)
    {
        std::cout << "Null\n";
    }
    std::cout << "Test \n";
}

在test1中,使用std::move(pD)作为参数调用F1,其中uPtr是对std::unique_ptr的右值引用。在调用F1之后,我检查了pD是否为空。我希望pD为null,因为std::move(pD)用于将其传递给F1,但它不是null。为什么会这样呢?
在test 2中,使用std::move(pD)作为参数调用F2,其中uPtr是std::unique_ptr类型的按值参数。在调用F2之后,我检查了pD是否为空。在这种情况下,pD为空。这正如我所料,因为std::move(pD)被用来将它传递给F2,但为什么这个行为与test1不同?
任何帮助将不胜感激!

6pp0gazn

6pp0gazn1#

直到调用了移动构造函数或移动赋值运算符后,对象才会移动。std::move只是一个从左值到右值的强制转换操作符,实际上没有数据在该点移动。std::move的一个更好的名称是std::cast_to_rvalue,但这有点冗长。
对于F1,指针通过右值 * 引用 * 传递,因此函数仍然使用来自调用者的示例。由于uPtr在函数中未被触及,因此原始指针仍然有效。
对于F2,指针是通过值传递的,因此在进入函数创建新对象之前,必须调用移动构造函数。即使指针在函数中未被触及,移动操作也已经发生,因此调用方的示例会受到影响。

bfrts1fy

bfrts1fy2#

这只是一个转换到r值引用

F1(std::move(pD));

The

void F1(std::unique_ptr<Dog>&& uPtr)
{
    std::cout << "F1 \n";
}

实际上对uPtr没有任何作用。它可以假设std_ptr即将被销毁,并使其处于不确定但有效的状态。你的不这样做。
F2正在使用移动构造函数,https://en.cppreference.com/w/cpp/memory/unique_ptr/unique_ptr查看构造函数5。

相关问题