【问题标题】:Why do I need to use std::move in the initialization list of a move-constructor?为什么我需要在移动构造函数的初始化列表中使用 std::move?
【发布时间】:2012-10-19 18:49:08
【问题描述】:

假设我有一个(平凡的)类,它可以移动构造和移动分配,但不能复制构造或复制分配:

class movable
{
  public:
    explicit movable(int) {}
    movable(movable&&) {}
    movable& operator=(movable&&) { return *this; }
    movable(const movable&) = delete;
    movable& operator=(const movable&) = delete;
};

这很好用:

movable m1(movable(17));

这当然行不通,因为m1 不是右值:

movable m2(m1);

但是,我可以将 m1 包装在 std::move 中,这会将其转换为右值引用,以使其工作:

movable m2(std::move(m1));

到目前为止,一切都很好。现在,假设我有一个(同样微不足道的)容器类,它包含一个值:

template <typename T>
class container
{
  public:
    explicit container(T&& value) : value_(value) {}
  private:
    T value_;
};

但是,这不起作用:

container<movable> c(movable(17));

编译器(我尝试过 clang 4.0 和 g++ 4.7.2)抱怨我试图在 container 的初始化列表中使用 movable 的已删除复制构造函数。同样,将 value 包裹在 std::move 中使其工作:

    explicit container(T&& value) : value_(std::move(value)) {}

但是为什么在这种情况下需要std::movevalue 不是已经属于 movable&amp;&amp; 类型了吗? value_(value)movable m1(movable(42)) 有何不同?

【问题讨论】:

  • 一个标准参考有望遵循,但并非所有 && 变量的使用都应该是破坏性的 - 你可以想象一个演员在丢弃它之前使用它的 && 参数采取了十几步。所以当你用 && 变量构造另一个对象时,你仍然需要说这个特殊用途是允许移动的……
  • T&amp;&amp; 类型的命名值是左值,而相同类型的未命名值是右值。
  • 在我的手机上,所以不会接听,但命名的临时是左值。这里,value 是一个左值表达式。
  • @Yakk:不需要标准参考。这是一个合适的答案。

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


【解决方案1】:

这是因为value 是一个命名变量,因此是一个左值。 std::move 需要将其强制转换为右值,以便匹配 T 的移动构造函数重载。

换一种说法:右值引用可以绑定到一个右值,但它本身不是一个右值。它只是一个引用,在表达式中它是一个左值。从中创建右值表达式的唯一方法是强制转换。

【讨论】:

    【解决方案2】:

    value_(value)movable m1(movable(42)) 有何不同?

    命名的右值引用是一个左值(因此将绑定到已删除的副本 ctor),而临时引用是一个右值(具体来说是一个纯右值)。

    §5 [expr] p6

    [...] 一般来说,这条规则的效果是命名的右值引用被视为左值,而对对象的未命名右值引用被视为xvalues [...]

    以及来自示例:

    A&& ar = static_cast<A&&>(a);
    

    表达式ar 是一个左值。

    以上引述来自非规范性注释,但足以解释,因为第 5 条的其余部分解释了哪些表达式创建 xvalues(又名, 只有指定的表达式,没有其他的会创建 xvalues)。有关详尽列表,另请参阅 here

    † xvalues 是 rvalues 的一个子组,prvalues 是另一个子组。有关说明,请参阅 this question

    【讨论】:

      猜你喜欢
      • 2018-01-13
      • 2013-06-06
      • 1970-01-01
      • 1970-01-01
      • 2015-03-21
      • 2013-01-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多