当前位置: 首页 > 知识库问答 >
问题:

不带std::move[重复]的右值引用

翁凯定
2023-03-14

我有以下课程

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构造函数。离开main方法,析构函数在<code>c<code>上调用。

现在是有趣的部分:

#include "widget.h"

auto main() -> int {

    widget c((widget()));
    c = widget();

    return 0;
};

如果我省略了对< code>std::move的调用,第一种情况会停止工作,只导致一次构造函数调用。而第二种情况仍然像以前一样工作。

我在这里错过了什么?为什么这两个函数调用以不同的方式处理它们的参数?我在gcc和clang上尝试了这个。

共有1个答案

长孙弘壮
2023-03-14

widget()是一个纯右值(prvalue),因此

widget c((widget())); // use widget c{widget()} or c{widget{}} for more clear code

它将被移动。但是,编译器只执行复制/移动省略。使用<code>-fno-elide构造函数进行编译

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

 类似资料:
  • 右值引用仅绑定可以移动的对象。如果你有一个右值引用参数,你就知道这个对象可能会被移动: class Widget { Widget(Widget&& rhs); //rhs definitely refers to an object eligible for moving ... }; 这是个例子,你将希望通过可以利用该对象右值性的方式传递给其他使用对象的函数。这样做的方法是将

  • 在我的Fedora 34环境(g)中,定义为: 如果表达式已经是右值,那么

  • 可能重复: 是传递const std::string的天数 如果支持移动语义学,我应该通过值传递d::字符串吗?那么使用小字符串优化(SSO)的实现呢?

  • 左值(赋值操作符“=”的左侧,通常是一个变量)与右值(赋值操作符“=”的右侧,通常是一个常数、表达式、函数调用)之间的差别可以追溯到 Christopher Strachey (C++的祖先语言CPL之父,指称语义学之父)时代。在C++中,左值可被绑定到非const引用,左值或者右值则可被绑定到const引用。但是却没有什么可以绑定到非const的右值(译注:即右值无法被非const的引用绑定),

  • 首先通过了解它们(指std::move和std::forward)不做什么来认识std::move和std::forward是非常有用的。std::move不move任何东西。std::forward也不转发任何东西。在运行时,他们什么都不做。不产生可执行代码,一个比特/Users/shikunfeng/Documents/neteaseWork/timeline_15_05_18/src/mai

  • 这两个函数完全匹配。以下是该标准的引用: 标准转换序列S1是比标准转换序列S2更好的转换序列,如果 ... S1和S2是引用绑定(8.5.3),都不引用未使用ref限定符声明的非静态成员函数的隐式对象参数,S1将右值引用绑定到右值,S2将左值引用绑定。 这不意味着第二个更好吗? 更新: 有一个相关的问题。下面的代码是它的简化版本。