移动构造函数和`std :: array`

23 c++ move-semantics c++11

根据N3485§23.3.2.2:

(...)数组的隐式移动构造函数和移动赋值运算符要求T 分别为MoveConstructibleMoveAssignable.

因此,std::array如果元素的类型支持,则支持移动语义.大!

但是,这究竟意味着什么?我倾向于将这种类型描述为提供符合STL标准的接口的更安全的数组版本,但是,如果这是真的,那么std::array移动构造它的元素怎么样?我可以用普通数组做同样的事情吗?

Mik*_*our 26

但是,这究竟意味着什么?

这意味着,如果元素类型是可移动的,那么数组类型也是如此.

std::array<movable, 42> move_from = {...};
std::array<movable, 42> move_to = std::move(move_from); // moves all the elements
Run Code Online (Sandbox Code Playgroud)

我倾向于将此类型描述为提供符合STL标准的接口的阵列的更安全版本

并不是的.它是数组的包装器,赋予它与聚合类相同的语义 - 包括复制和移动它的能力.

如何std::array移动 - 构建其元素?

与任何其他聚合完全相同.它的隐式移动构造函数将移动构造其所有成员,包括任何成员数组的元素.

我可以用普通数组做同样的事情吗?

只有将它包装在类类型中时std::array才会这样.

  • @faranwath:确实 - 具体来说,用户定义的聚合类型隐式生成了移动构造函数. (9认同)

Rei*_*ica 21

移动a std::array与移动a不同std::vector.当一个移动std::vector到另一个时,它(有时*)可以简单地重新定位内部指针并避免操纵元素.

有了std::array,这当然是不可能的 - 它的元素具有自动存储持续时间,它们实际上包含在对象内.但是,它们中的每一个仍然可以被移动,这就是移动操作std::array所做的事情**.

*假设分配器兼容并且不禁止此操作

**std::vector当缓冲区不能仅由目标向量重新拥有时,这也是你得到的.


dyp*_*dyp 7

(非联合)类的默认移动构造函数执行成员移动.移动原始数组数据成员意味着移动每个数组的元素,请参阅[class.copy]/15.

因此,您可以通过将原始数组放在类中来移动它:

struct wrap
{
    std::string arr[25];
};

auto w = wrap();
auto m = std::move(w); // moves the 25 `std::string`s
Run Code Online (Sandbox Code Playgroud)

您还可以手动调用元素的移动构造函数,例如:

std::string a[3] = { /*...*/ };
std::string b[3] = {std::move(a[0]), std::move(a[1]), std::move(a[2])};
Run Code Online (Sandbox Code Playgroud)

如果std::array包含原始数组,则不指定.但是,它确实包含数据成员value_type,因为它保证是一个聚合.调用移动构造函数时,将按照上述方法移动这些数据成员.

如果a的数据成员std::array不是MoveConstructible,则实例化其移动构造函数将失败.