gpt4 book ai didi

c++ - 为什么临时 'Test'没有移动,而只是构造?

转载 作者:太空宇宙 更新时间:2023-11-04 12:33:58 25 4
gpt4 key购买 nike

我正在阅读 Scott Meyers 的 Effective Modern C++ 这本书,作者在其中提到了

"Copies of rvalues are generally move constructed, while copies of lvalues are usually copy constructed."

所以我想通过编写 Test 来测试它将在旅途中临时构建的类 dummy将右值引用作为 Test 参数的函数类。

我期待看到上面引用的输出,如:

Constructed...
Moving...
Hello world

但我只有:

Constructed...
Hello world

为什么移动构造函数没有调用?将临时传递给 dummy 是否有任何未定义的行为喜欢dummy(Test{}); ?我正在使用 C++17。

代码如下:

#include <iostream>

class Test
{
public:
Test() { std::cout << "Constructed...\n"; }
Test(const Test&) { std::cout << "Coping...\n"; }
Test& operator=(const Test&) { std::cout << "Copy=...\n"; return *this; }
Test(Test&&) { std::cout << "Moving...\n"; }
Test& operator=(Test&&) { std::cout << "Move=...\n"; return *this; }
void print() const
{
std::cout << "Hello world\n";
}
};

void dummy(Test&& test)
{
test.print(); // is the behavior is good?
}

int main()
{
dummy(Test{});
return 0;
}

最佳答案

出于同样的原因,下面的代码不会调用复制构造函数:

class Test {
...
};

void dummy(Test& t) { // passed as an lvalue reference
test.print();
}

int main() {
Test t;
dummy(t);
return 0;
}

...因为对象是通过引用传递的。在上面的代码中,它是一个左值引用,而在您给出的示例中它是一个右值引用,但仍然是一个引用。

相比之下,如果你想按值传递它,你需要在你的函数参数类型中反射(reflect)它:

void dummy(Test t) {
...
}

然后需要调用构造函数以按值传递t除非发生复制省略,请参见下面的添加

注意 std::move 实际上并没有移动任何东西。它将输入转换为右值引用并将其返回。


虽然有一点细微差别。 C++17 保证不会为纯右值赋值创建临时对象,即 dummy(Test{}) 在这种情况下不会调用复制或移动构造函数,因为创建临时对象被省略了。尽管语言不需要,但复制省略可能仍会在 C++17 之前的版本中发生。因此,如果您想观察在将 prvalue Test{} 按值传递给 时调用移动构造函数,请务必设置 -fno-elide-constructors 编译器标志>dummy 函数(如上例所示)。

关于c++ - 为什么临时 'Test'没有移动,而只是构造?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57243741/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com