【发布时间】:2015-03-04 19:42:16
【问题描述】:
为什么在 const 对象上调用 std::move 在传递给另一个对象时会调用复制构造函数?具体代码
#include <iostream>
struct Foo {
Foo() = default;
Foo(Foo && x) { std::cout << "Move" << std::endl; }
Foo(Foo const & x) = delete;
};
int main() {
Foo const x; Foo y(std::move(x));
}
编译失败:
g++ -std=c++14 test07.cpp -o test07
test07.cpp: In function 'int main()':
test07.cpp:10:36: error: use of deleted function 'Foo::Foo(const Foo&)'
Foo const x; Foo y(std::move(x));
^
test07.cpp:6:5: note: declared here
Foo(Foo const & x) = delete;
^
Makefile:2: recipe for target 'all' failed
make: *** [all] Error 1
当然,我预计它会失败,因为我们无法移动 const 值。同时,我不明白代码在尝试调用复制构造函数之前所采用的路线。意思是,我知道 std::move 将元素转换为 x 值,但我不知道之后关于 const 的事情如何进行。
【问题讨论】:
-
被移动对象的
constness没有改变,Foo const&&不能绑定到Foo&&所以编译器尝试访问复制构造函数,因为它被删除了失败。跨度> -
我不是移动运算符方面的专家,但也许你可以在
const值上调用 move,但其结果只能被复制构造函数接受,因此编译器决定调用它。 -
"意思是,我知道 std::move 将元素转换为 x 值" 实际上,它没有。它返回对项目的右值引用。
-
@BenVoigt,有什么区别? [basic.lval] "调用返回类型为对对象类型的右值引用的函数的结果是一个xvalue。"
-
@BenVoigt
std::move(v)的结果是转换表达式v的结果(这是一个左值和一个对象,但不是左值引用,因为表达式没有引用类型, [expr]/5) 输入Foo&&(这是一个 xvalue)...我认为说它不会将 v 转换为 xvalue 是不必要的迂腐,或者完全是错误的。