为什么C++左值对象不能绑定到右值引用(&&)?

pav*_*din 11 c++ rvalue-reference move-semantics c++11

移动语义的想法是,您可以从另一个临时对象(由右值引用引用)中获取所有内容,并将"所有内容"存储在对象中.这有助于避免在单个构造事物足够的情况下进行深度复制 - 因此您可以在rvalue对象中构造事物,然后将其移动到长寿命对象中.

为什么C++不允许将左值对象绑定到右值引用?两者都允许我更改引用的对象,因此在访问引用对象的内部方面对我没有任何区别.

我能猜到的唯一原因是函数重载模糊问题.

Use*_*ess 22

但是为什么C++不允许将左值对象绑定到右值引用?

假设你的意思是"为什么C++不允许将左值引用绑定到左值对象":它确实如此.它不是自动的,所以你必须使用std::move它来使它明确.

为什么?因为否则一个无害的函数调用会令人惊讶地破坏你没想到的东西:

Class object(much,state,many,members,wow);
looks_safe_to_me(object);
// oh no, it destructively copied my object!
Run Code Online (Sandbox Code Playgroud)

Class object(much,state,many,members,wow);
obviously_destructive(std::move(object));
// same result, but now the destruction is explicit and expected
Run Code Online (Sandbox Code Playgroud)

关于破坏性复制的注释:为什么我说破坏性破坏上面,我并不是说对象析构函数结束它的生命周期:只是它的内部状态已被移动到一个新实例.它仍然是一个有效的对象,但不再拥有以前相同的昂贵状态.


关于术语的说明:让我们看看我们是否可以清除上面对左值,右值等的不精确使用.

引用后代的cppreference:

  • 一个左值

    具有身份无法移动的表达式.

    所以,没有lvalue对象这样的东西,但是有一个由左值表达式在本地命名(或引用)的对象

  • 一个右值

    一个表达式,它是一个prvalue或一个xvalue.它可以从.它可能有也可能没有身份.

    • 一个prvalue(纯右值)大致指的是一个未命名的临时对象的表达式:我们不能我们的左值表达式转换成这些IIUC之一.

    • 一个x值(到期值)为

      一个具有身份可以移动的表达式.

      明确包括结果 std::move

那么实际发生了什么:

  • 存在一个对象
  • 该对象由左值表达式在本地标识,该表达式无法移动(以保护我们免受意外的副作用)
  • std::move 产生一个xvalue表达式(可以从中移动)引用与左值表达式相同的对象
  • 这意味着变量(由左值表达式命名)等对象不能隐式移动,而必须通过显式xvalue表达式显式移出,例如std::move.
  • 匿名临时值可能已由prvalue表达式引用,并且可以隐式移动

  • 当使用`std :: move`时,没有将右值引用绑定到左值。您正在将左值强制转换为右值,然后将右值引用绑定到该右值。 (2认同)
  • @Useless但是对象没有值类别,表达式有。表达式“object”是左值,表达式“std::move(object)”是右值。 (2认同)