C++ 不带std::move的右值引用
我有以下课程C++ 不带std::move的右值引用,c++,c++11,move,rvalue-reference,move-constructor,C++,C++11,Move,Rvalue Reference,Move Constructor,我有以下课程 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&; au
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;
};
由此产生的行为对我来说是可以理解的。在第一次调用中,构造一个小部件,然后调用move构造函数,并在临时小部件上调用析构函数
第二个调用也执行相同的操作,除了调用move赋值操作符而不是move构造函数。
离开main方法,在c
上调用析构函数
现在是有趣的部分:
#include "widget.h"
auto main() -> int {
widget c((widget()));
c = widget();
return 0;
};
如果我省略了对std::move
的调用,那么第一个案例将停止工作,只会导致一个构造函数调用。而第二个案例仍然像以前一样有效
我错过了什么?为什么这两个函数调用对其参数的处理方式不同?
我在gcc和clang上尝试了这个方法。widget()
是一个纯右值(prvalue),因此
widget c((widget())); // use widget c{widget()} or c{widget{}} for more clear code
它将被移动。然而,编译器只是执行。使用-fno elide构造函数编译,您将看到对move构造函数的调用
无论何时显式使用std::move
移动prvalue,都不允许编译器执行省略;这就是为什么在第一个代码段中可以看到move构造函数在运行。这就是为什么尝试使用std::move
作为返回来“帮助”编译器几乎总是一个坏主意(除非您真的想返回右值引用)。(widgeht())
是一个prvalue,即右值,因此它会被移动(如果可能的话)std::move
不移动,它只是更改表达式的值类别。如果该表达式具有相应的值类别,那么它是多余的。括号是必需的,否则,表达式将作为指向不带参数并返回小部件的函数指针进行计算。可能是您的编译器正在为您优化某些构造并进行复制吗?请尝试使用-fno elide构造函数进行编译。您的副本将被删除(只有当c
由非引用指定的临时文件初始化时,才能使用)。是的,额外的参数是必要的。否则,它是一个函数声明,而不是对象定义。@BenjaminLindley你说得对,我编辑了它。出于某种原因,我错误地认为widget
是一个对象,而不是类的名称。