协慌网

登录 贡献 社区

什么是 std :: move(),何时应使用它?

  1. 它是什么?
  2. 它有什么作用?
  3. 什么时候应该使用?

良好的链接表示赞赏。

答案

Wikipedia 页面上的 C ++ 11 R 值引用和移动构造函数

  1. 在 C ++ 11 中,除了复制构造函数之外,对象还可以具有 move 构造函数。
    (并且除了复制分配运算符外,他们还具有移动分配运算符。)
  2. Type && ),那么将使用 move 构造函数而不是 copy 构造函数。
  3. std::move()是一种强制类型转换,它生成对对象的右值引用,从而能够从该对象进行移动。

这是避免复制的新 C ++ 方法。例如,使用 move 构造函数, std::vector可以将其内部指针复制到数据中,并将其复制到新对象中,而使移动后的对象处于从状态移出的状态,因此不复制所有数据。这将是 C ++ 有效的。

尝试谷歌搜索以获取移动语义,右值,完美转发。

1.“这是什么?”

虽然std::move()从技术上讲是一个函数 - 我会说它并不是一个真正的函数。它在编译器考虑表达式值的方式之间是一种转换器。

2.“它是做什么的?”

首先要注意的是std::move()实际上并没有移动任何东西。它将表达式从左值(例如命名变量)更改为xvalue 。一个 xvalue 告诉编译器:

您可以掠夺我,我持有的任何物品转移到其他地方使用(因为无论如何我都会很快被销毁)”。

换句话说,当您使用std::move(x) ,您将允许编译器吞并x 。因此,如果x在内存中拥有自己的缓冲区,则在std::move() ,编译器可以拥有另一个对象。

您也可以从prvalue (例如您要经过的临时地址)移开,但这很少有用。

3.“何时应使用?”

提出此问题的另一种方式是 “我将蚕食现有对象的资源用于什么?” 好吧,如果您正在编写应用程序代码,则可能不会把编译器创建的临时对象弄得一团糟。因此,主要是在诸如构造函数,运算符方法,标准库算法之类的函数等位置执行此操作,在这些位置会大量自动创建和销毁对象。当然,这只是一个经验法则。

一种典型的用法是将资源从一个对象 “移动” 到另一个对象,而不是复制。 @Guillaume 链接到此页面,该页面有一个简单的简短示例:交换两个对象且复制较少。

template <class T>
swap(T& a, T& b) {
    T tmp(a);   // we now have two copies of a
    a = b;      // we now have two copies of b (+ discarded a copy of a)
    b = tmp;    // we now have two copies of tmp (+ discarded a copy of b)
}

使用 move 允许您交换资源,而不是在周围复制资源:

template <class T>
swap(T& a, T& b) {
    T tmp(std::move(a));
    a = std::move(b);   
    b = std::move(tmp);
}

T是大小为 n 的vector<int>时会发生什么。在第一个版本中,您读写 3 * n 个元素,在第二个版本中,您基本上只读写 3 个指向向量缓冲区的指针,加上 3 个缓冲区的大小。当然, T类需要知道如何进行移动。 T配备一个移动分配运算符和一个移动构造函数,以使其正常工作。

当需要将对象的内容 “转移” 到其他地方而不进行复制时,可以使用 move 方式(即,内容不重复,这就是为什么可以将其用于某些不可复制的对象(例如 unique_ptr)的原因)。一个对象也可以使用 std :: move 来获取临时对象的内容而无需执行复制操作(并节省大量时间)。

这个链接确实帮助了我:

http://thbecker.net/articles/rvalue_references/section_01.html

很抱歉,我的答案来不及了,但是我也正在为 std :: move 寻找一个好的链接,我发现上面的链接有点 “严肃”。

这将重点放在 r 值引用上,在这种情况下您应该使用它们,而且我认为它更详细,这就是为什么我想在这里共享此链接。