当你有一个带有移动构造函数的派生对象,并且基础对象也有移动语义时,从派生对象移动构造函数调用基础对象移动构造函数的正确方法是什么?
我首先尝试了最明显的事情:
Derived(Derived&& rval) : Base(rval)
{ }
但是,这似乎最终调用了Base对象的复制构造函数。然后我尝试在这里明确使用std::move
,如下所示:
Derived(Derived&& rval) : Base(std::move(rval))
{ }
这很有效,但我很困惑为什么这是必要的。我以为std::move
只返回一个右值引用。但由于在此示例中rval
已经是右值引用,因此对std::move
的调用应该是多余的。但是如果我不在这里使用std::move
,它只是调用复制构造函数。那么为什么要调用std::move
呢?
答案 0 :(得分:36)
rval
不是Rvalue。它是移动构造函数体内的左值。这就是我们必须明确调用std::move
。
参考this。重要的是
请注意,参数x是 被视为内部的左值 移动功能,即使它是 声明为右值参考 参数。这就是必要的原因 说移动(x)而不只是x时 传递给基类。这个 是移动的关键安全功能 旨在防止的语义 意外地从一些人移动两次 命名变量。所有动作仅发生 来自rvalues,或者使用明确的演员 使用std :: move等rvalue。如果 你有一个变量的名称,它 是一个左值。
答案 1 :(得分:0)
已命名的R值引用被视为L值。
因此,我们需要std::move
才能将其转换为R值。
答案 2 :(得分:-4)
你真的应该使用std :: forward(obj)而不是std :: move(obj)。 Forward将根据obj返回正确的rvalue或lvalue,而move会将左值变为rvalue。