从技术上讲,什么是移动对象?

What is technically a moved-from object?

根据标准,您只能certain things对移出的对象进行操作。但是,什么在技术上被视为移出对象?

假设我这样做:

int x = 42;
std::move(x);
int y = x; // is this ok?

std::move 只是对右值引用的转换。如果这个引用没有被消耗,那算不算移动?在调用 std::move 之后,我还能在上面的示例中使用 x 吗?

好吧,std::move(x); 只是转换为 r 值引用 - 它什么都不做。但是好吧,假设你有这个:

int x = 42;
int z = std::move(x);
int y = x; // is this ok?

是的,没问题,x, y, z 都将是 42。因为对于普通类型,移动与复制相同。

但是其他更复杂的 类 呢?

一般来说,移动和移出对象只有几个严格的要求。

  1. 移出的对象需要 copy/move 可分配且可破坏。
  2. 目标应该与预先移动的源“相等”。

这些要求是必要的。许多 STL 功能和其他库将无法使用不支持这些功能的类型正常运行。

实际上,简单的 POD 类型只是在移动时执行复制,而容器将资源所有权从源转移到目标,同时销毁目标拥有的任何资源。从技术上讲,对象之间的数据交换也是一种合法的行为——有些人认为这是一个好主意——我强烈反对它,因为如果我想交换数据,那么我会触发 std::swap 而不是 std::move.

然而,没有严格的要求必须对移出对象执行什么操作 - 这在处理复杂 类 时很重要。例如,可以为 std::vector 编写一个自定义分配器,明确禁止移动,在这种情况下,移动时会发生某种数据复制和数据移动混合的情况,不同版本的 STL 可能会或可能不会清除原始数据对象。

注意事项:cppreference 已在文档中明确说明对大多数 类 的移出对象的要求。所以你会知道到底会发生什么,而且它并不总是直观的。通常他们会尽可能地采取最懒惰的行动。