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

时间:2018-06-10 18:18:28

标签: c++

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

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

或者这个:

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

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

2 个答案:

答案 0 :(得分:0)

你应该使用第二种方法。

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

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

答案 1 :(得分:0)

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

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

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