c++ - 没有 std::move 的右值引用

标签 c++ c++11 move rvalue-reference move-constructor

<分区>

我有以下类(class)

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

它会被 move 。但是,编译器只执行 copy/move elision .使用 -fno-elide-constructors 进行编译,您将看到对 move 构造函数的调用非常出色。

每当您显式使用 std::move move 纯右值时,您就不允许编译器执行省略;这就是为什么您会在第一个片段中看到正在运行的 move 构造函数。这就是为什么尝试通过使用 std::move 作为返回来“帮助”编译器几乎总是一个坏主意(除非你真的想返回一个右值引用)。

关于c++ - 没有 std::move 的右值引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30057944/

相关文章:

c++ - std::cout 功能的特殊行为

c++ - 找到OpenCV.cmakeConfig.cmake

c++ - 以下代码片段 C++ 的说明

c++ - unique_ptr - 无效指针和段错误

c++ - 当 move 和复制构造函数都存在时,将调用哪一个?

c++ - move 对象 (OpenGL)

c++ - 使用模板类作为参数

c++ - #include 指令 : relative to where?

c++ - 双重检查锁定 : Fences and atomics

xml - 使用 sed 在 xml 上 move 文本