在移动构造函数中使用std :: move

时间:2016-05-04 10:11:39

标签: c++11

This answer写一个这样的移动构造函数:

dumb_array(dumb_array&& other)
        : dumb_array() // initialize via default constructor, C++11 only
    {
        swap(*this, other);
    }

注意:此swap是在类上定义的自定义交换,而不是std::swap

This answer建议使用std::move

  

你应该只在适当的时候调用std :: move,但这是个人偏好。

我刚刚观看了一个关于移动语义的Scott Meyers谈话,他说,作为函数参数的 rvalue引用由于它现在被命名,因此被转换回左值,因此std :: move是必要的再次把它变回右值

换句话说,上面的代码很可能不会进行移动操作,并且与上面的引文不同,在这种情况下使用std::move不是关于个人偏好,而是关于实际获得移动的好处语义。

如果在移动构造函数或移动赋值运算符中没有明确使用std::move,那么移动可能实际上并没有发生,而是正在进行复制吗?

2 个答案:

答案 0 :(得分:4)

  

如果在移动构造函数或移动赋值运算符中没有明确使用std::move,那么移动可能实际上并没有发生,而是正在进行复制吗?

不,这肯定不准确。在问题的特定情况下,它完全取决于swap的实施。

一个自然的实现是swap(dumb_array&, dumb_array&),它在内部交换一些指针,可能是这样的:

void swap(dumb_array &lhs, dumb_array &rhs)
{
  std::swap(lhs.pointer_to_data, rhs.pointer_to_data);
}

如果是这种情况,那么你所展示的移动构造函数肯定会执行轻量级移动 - 只是指针交换。其次,在调用std::move时使用swap将完全错误,因为swap需要左值引用。

答案 1 :(得分:1)

  

我刚刚观看了一个关于移动语义的Scott Meyers的演讲,他说当一个rvalue引用作为一个函数参数由于它现在已被命名而被转回到左值,因此std :: move是必需的再把它变回右值。

那是对的。

但是围绕这个话题存在许多误解。

  

换句话说,上面的代码很可能不会进行移动操作

它不会采取行动。但是,swap可能无论如何都是有效的操作,因此您无需关心。

  

在这种情况下使用std :: move是关于实际获得移动语义的好处。

不正确。即使您使用std::move,也无法保证会发生任何移动。

  

是否准确地说如果在移动构造函数或移动赋值运算符中没有明确使用std :: move,那么移动可能实际上并没有发生,而是正在复制?

即使没有std::move,也可能会发生移动。

所以基本上,std::move既不是必要的,也不足以让它发生。这似乎很令人惊讶。

我认为这没有捷径。如果你想了解这一点,找一个很好的综合教程。例如。托马斯·贝克尔受欢迎的C++ Rvalue References Explained