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

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

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

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

我能猜到的唯一原因是函数重载歧义问题。

最佳答案

But why C++ doesn't allow binding lvalue objects to rvalue references?

假设您的意思是“为什么 C++ 不允许将右值引用绑定(bind)到左值对象”:它允许。它只是不是自动的,因此您必须使用 std::move 使其显式化。

为什么?因为否则一个无害的函数调用可能会出人意料地破坏一些你没有预料到的东西:

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

对比

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

关于破坏性复制的注意事项:为什么我在上面说破坏性破坏,我并不是说对象析构函数结束了它的生命周期:只是它的内部状态已经 move 到一个新的实例。它仍然是一个有效的对象,但不再像以前那样拥有昂贵的状态。


关于术语的注释:让我们看看是否可以消除上面对左值右值等的不精确使用。

引自cppreference为了后代:

  • lvalue

    an expression that has identity and cannot be moved from.

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

  • rvalue

    an expression that is either a prvalue or an xvalue. It can be moved from. It may or may not have identity.

    • prvalue(纯右值)大致是一个引用未命名临时对象的表达式:我们无法将左值表达式转换为这些 IIUC 之一。

    • xvalue(到期值)是

      an expression that has identity and can be moved from.

      明确包含 std::move

    • 的结果

那么实际发生了什么:

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

关于c++ - 为什么 C++ 左值对象不能绑定(bind)到右值引用 (&&)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35652953/

相关文章:

c++ - 为读和写定义运算符 [ ]

c++ - 从属名称的模板消歧器

c++ - 如何在类上下文中使用 std::mutex

c++ - 尽管传递了一个右值,为什么我的 move 构造函数没有被调用?

c++ - 处理 QListWidget 点击和滚动

c++ - Windows 10 特定崩溃调用 LeaveCriticalSection

c++ - SFML 2.0 循环使用相同的 Sprite

c++ - 从函数返回一个 unique_ptr vector

c++ - D 是否有类似于 C++0x 的 move 语义的东西?

c++ - 这是对 move 语义的滥用/误用吗?