我写了两组函数,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不同?
任何帮助将不胜感激!
2条答案
按热度按时间6pp0gazn1#
直到调用了移动构造函数或移动赋值运算符后,对象才会移动。
std::move
只是一个从左值到右值的强制转换操作符,实际上没有数据在该点移动。std::move
的一个更好的名称是std::cast_to_rvalue
,但这有点冗长。对于
F1
,指针通过右值 * 引用 * 传递,因此函数仍然使用来自调用者的示例。由于uPtr
在函数中未被触及,因此原始指针仍然有效。对于
F2
,指针是通过值传递的,因此在进入函数创建新对象之前,必须调用移动构造函数。即使指针在函数中未被触及,移动操作也已经发生,因此调用方的示例会受到影响。bfrts1fy2#
这只是一个转换到r值引用
The
实际上对uPtr没有任何作用。它可以假设std_ptr即将被销毁,并使其处于不确定但有效的状态。你的不这样做。
F2
正在使用移动构造函数,https://en.cppreference.com/w/cpp/memory/unique_ptr/unique_ptr查看构造函数5。