移动对象后支持的操作是什么?

时间:2014-02-21 11:26:39

标签: c++ c++11 move-semantics

如果某个对象实际移动到另一个位置,原始对象支持的操作是什么?

为了详细说明,我有一个带有可用移动构造函数的T类型。以下陈述

T x{constructor-args};
T y{std::move(x)};

使用对象x可以完成所有操作(假设对象实际上使用x的可用移动构造函数从y移动到T

具体地,

  • x肯定会被销毁。我可以假设移动后x可以轻易破坏吗?
  • 可以x分配或移动分配给新对象(我想是的,因为我看到很多swap使用了这个)?
  • 我可以构建一个新的对象对象来代替x吗?如果允许这是允许的话,那么是否可以使用uninitialized_move与(部分)重叠源和&目的地范围,如std::copy,与std::uninitialized_copy不同?

    T z{some-args};
    x = z; //or x = std::move(z);
    T u{some-args};
    new(&x) T{std::move(u)}; // or new(&x) T{u}; etc
    

2 个答案:

答案 0 :(得分:3)

无论你定义它是什么。至少,由此产生 对象应该是可破坏的 - 它的析构函数将是 调用,对象的状态应该是这样的 没有问题。

标准库保证其对象是一些 连贯的国家。你可以调用任何成员函数:它是 未指明您得到的回报,结果将是 连贯:如果你在已被移动的向量上调用size, 您也可以使用小于该值的索引来调用operator[]size返回(但在唯一合理的实施中, size将返回0,)。这可能不仅仅是什么 然而,有效使用所需;所有这些都是非常必要的 是调用析构函数将工作。

为了更清楚,以std::vector为例:如果我们 假设通常的实现,有三个指针,开始, 结束和限制(或者他们被称为:限制意味着 一个超过分配内存的末尾,以便capacity() 返回limit - begin)。搬家后,标准会 要求所有三个指针都为空。多数情况 实现中,不会访问限制指针 析构函数,因此可删除的宽松要求会 如果只将开始和结束指针设置为null,则会遇到。

答案 1 :(得分:2)

关于图书馆类型,标准说(17.6.5.15)

  

除非另有说明,否则此类移动对象应置于有效但未指定的状态。

这意味着它们至少应该是可破坏和可分配的。正如詹姆斯在下面提到的那样,该对象仍然应该遵循自己的界面。你自己的类型应遵循相同的想法。

你不应该使用placement-new来做这类事情。假设移动构造函数不存在,并使用operator =以与以前相同的方式编写代码。示例中的最后一行应为x=std::move(u);x=u;