58

当您有一个带有移动构造函数的派生对象,并且基础对象也具有移动语义时,从派生对象移动构造函数调用基础对象移动构造函数的正确方法是什么?

我首先尝试了最明显的事情:

 Derived(Derived&& rval) : Base(rval)
 { }

但是,这似乎最终调用了 Base 对象的复制构造函数。然后我尝试std::move在这里明确使用,如下所示:

 Derived(Derived&& rval) : Base(std::move(rval))
 { }

这行得通,但我很困惑为什么它是必要的。我以为std::move只是返回一个右值引用。但是因为在这个例子rval中已经是一个右值引用,所以调用std::move应该是多余的。但是如果我不在std::move这里使用,它只是调用复制构造函数。那么为什么std::move需要调用呢?

4

3 回答 3

52

rval不是右值。它是移动构造函数体内的左值。这就是为什么我们必须显式调用std::move.

参考这个。重要的注意事项是

请注意,参数 x 被视为移动函数内部的左值,即使它被声明为右值引用参数。这就是为什么在传递给基类时必须说 move(x) 而不仅仅是 x 的原因。这是移动语义的一个关键安全特性,旨在防止从某个命名变量意外移动两次。所有移动仅从右值发生,或通过显式转换为右值发生,例如使用 std::move。如果您有变量的名称,它是一个左值。

于 2010-11-03T12:01:44.437 回答
2

命名的 R 值引用被视为 L 值。

所以我们需要std::move将其转换为 R-Value。

于 2020-05-14T10:37:04.513 回答
-5

你真的应该使用 std::forward(obj) 而不是 std::move(obj)。Forward 将根据 obj 是什么返回正确的右值或左值,而 move 会将左值转换为右值。

于 2011-02-01T18:48:22.273 回答