在构造函数中初始化成员时,是否应该在成员上使用 std::move?

Should std::move be used on members when initializing them in the constructor?

本文关键字:成员 std move 构造函数 初始化 是否      更新时间:2023-10-16

我一直在尝试完全理解移动语义,但我有一个问题,因为不同的示例显示了不同的东西。 假设我们有一个具有字符串成员str_的类 Foo。要定义移动构造函数,我应该这样定义它:

Foo(Foo&& foo) : str_(foo.str_) { }

或者这个:

Foo(Foo&& foo) : str_(std::move(foo.str_)) { }

另外,我是否需要将要从中移动的对象的成员设置为空白值?如何在不构造另一个字符串的情况下做到这一点,基本上抵消了首先使用 move 构造函数节省的费用?

您应该使用第二种方法。

您不必对从中移动的string执行任何操作,因为这是由string的 move 构造函数处理的。 后者由move()调用调用。

你自己的类也是如此,任何你想move()的东西都应该有一个移动构造函数。 例如,如果您的类具有指针成员,则 move 构造函数可以/应该将nullptr分配给您从中move()的对象中的该成员。

在移动构造函数(或移动赋值运算符(中,在移动单个成员时需要使用std::move()(或者至少在非 POD 成员上,因为"移动"POD 类型与复制它相同(。

Foo&& foo中,foo是一个右值引用,但foo.str_不是。如果在移动构造函数中调用str_(foo.str_)(或在移动赋值运算符中调用str_ = foo.str_(,它将调用字符串的复制构造函数(或复制赋值运算符(。因此,您需要通过std::move()foo.str_强制转换为右值引用,以便调用字符串的移动构造函数(或移动赋值运算符(。

移动构造函数(和移动赋值运算符(负责使 moved-from 对象处于未指定但有效的状态,因此其析构函数不会失败。 在移动foo.str_成员的情况下,字符串的移动构造函数(或移动赋值运算符(将为您重置foo.str_为空字符串,您无需手动重置它。