【发布时间】:2015-07-15 11:32:02
【问题描述】:
我有以下课程
class widget {
// The methods only print their name, i.e. c'tor, destructor etc.
public:
widget();
widget(const widget&);
widget(widget&&);
~widget();
auto operator=(const widget&) -> widget&;
auto operator=(widget&&) -> widget&;
};
我在下面的代码中使用
#include "widget.h"
auto main() -> int {
widget c(std::move(widget()));
c = std::move(widget());
return 0;
};
由此产生的行为对我来说是可以理解的。在第一次调用中构造一个小部件,然后调用移动构造函数并在临时小部件上调用析构函数。
第二次调用也是如此,只是调用移动赋值运算符而不是移动构造函数。
离开 main 方法,在c 上调用析构函数。
现在有趣的部分来了:
#include "widget.h"
auto main() -> int {
widget c((widget()));
c = widget();
return 0;
};
如果我忽略了对std::move 的调用,第一种情况将停止工作并只调用一个构造函数。而第二种情况仍然像以前一样工作。
我在这里缺少什么?为什么这两个函数调用以不同的方式处理它们的参数? 我在 gcc 和 clang 上试过这个。
【问题讨论】:
-
(widghet())是一个prvalue,即一个右值,因此它被移动(如果可能的话)。std::move不动,它只是改变了表达式的值类别。如果该表达式无论如何都有相应的值类别,那就是多余的。 -
括号是必需的,否则表达式被评估为指向不带参数并返回
widget的函数的函数指针。 -
会不会是您的编译器正在为您优化一些结构和副本?
-
尝试使用
-fno-elide-constructors编译。您的副本正在被省略(仅当c由未由引用指定的临时初始化时才有效)。
标签: c++ c++11 move rvalue-reference move-constructor