【问题标题】:Will a value be moved in this case在这种情况下是否会移动一个值
【发布时间】:2017-12-20 07:18:03
【问题描述】:

考虑以下 sn-p:

class Bar {...};
class Foo {
  public:
    Foo(const Bar& bar): bar_(bar) {}
  private:
    Bar bar_;
};

int main() {
    Foo foo({...});  // Passing an rvalue Bar object here.
}

问题:我生成的对象会被复制到 Foo 的构造函数中,还是会被移动?更准确地说,以下哪项是正确的?

  • 它将始终被复制。
  • 它总是会被移动(我很确定不是这样)。
  • 这是未指定的行为。

【问题讨论】:

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


    【解决方案1】:

    它会一直被复制。

    您创建的 rvalue 绑定到 const 左值引用。但即使它被绑定到一个右值引用,你也可以从一个左值(bar)构造bar_(bar)。 绑定到引用的对象的值类别没有实际意义,重要的是引用本身的值类别。就像已经提到的,表达式bar 是一个左值。

    作为一个通用且有点粗略的经验法则,作为某事物名称的每个表达式都是一个左值。

    如果你想在一个构造函数中同时支持移动和复制,前进的方法是这样的:

    Foo(Bar bar): bar_(std::move(bar)) {}
    

    现在bar 可以通过移动副本来构建,具体取决于源,并且您的成员是由您可以安全移出的对象构建的。当然,这总是会产生额外的动作。如果你想避免它,那么需要两个 c'tors:

    Foo(const Bar& bar): bar_(bar) {}
    Foo(Bar&& bar): bar_(std::move(bar)) {}
    

    【讨论】:

    • 这就是我所期望的。但是,这不是一般情况下可以安全地进行移动而不是复制的情况之一吗?我有点希望现代编译器可以为我做这种优化,让我保留一个(IMO 更具可读性)的 const 参考形式而不牺牲性能。但这当然会导致这种未指定的行为。所以你是说这在标准中是固定的,copy 永远不能用 move here 代替,对吧?
    • @SolenodonParadoxus - 这并不安全。移动是在本地完成的,在 c'tor 中。但参数不必绑定到rvalue(对象在函数之外)。考虑单独编译。您将一个对象与您的 c'tor 链接起来(假设它只提供右值)。然后执行此操作:Bar b; Foo f(b);。这是合法的 C++。你不能让它不合法。
    • @SolenodonParadoxus - 是的,副本就是副本。如果我们想要一个动作,那么我们需要拼出一个动作。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-28
    • 2012-10-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-09
    相关资源
    最近更新 更多