151

标准是否准确定义了一个对象一旦被移出我可以做什么?我曾经认为你可以对一个移动的对象做的就是破坏它,但这还不够。

例如,以swap标准库中定义的函数模板为例:

template <typename T>
void swap(T& a, T& b)
{
    T c = std::move(a); // line 1
    a = std::move(b);   // line 2: assignment to moved-from object!
    b = std::move(c);   // line 3: assignment to moved-from object!
}

显然,必须可以分配给移动对象,否则第 2 行和第 3 行将失败。那么我还能对移动的对象做什么呢?我究竟在哪里可以找到标准中的这些细节?

(顺便说一句,为什么它T c = std::move(a);不是T c(std::move(a));在第 1 行?)

4

2 回答 2

127

17.6.5.15 [lib.types.movedfrom]

C++ 标准库中定义的类型的对象可以从 (12.8) 中移出。移动操作可以显式指定或隐式生成。除非另有说明,否则此类移出的对象应置于有效但未指定的状态。

当对象处于未指定状态时,您可以对该对象进行任何没有前置条件的操作。如果您希望执行带有前提条件的操作,则不能直接执行该操作,因为您不知道对象的未指定状态是否满足前提条件。

通常没有前置条件的操作示例:

  • 破坏
  • 任务
  • const 观察者,例如get, empty,size

通常确实有先决条件的操作示例:

  • 取消引用
  • pop_back

这个答案现在以视频格式出现在这里:http ://www.youtube.com/watch?v=vLinb2fgkHk&t=47m10s

于 2011-08-11T15:09:57.783 回答
60

移出对象以未指定但有效的状态存在。这表明虽然对象可能不再有能力做很多事情,但它的所有成员函数仍应表现出定义的行为——包括operator=——以及处于定义状态的所有成员——并且它仍然需要销毁。该标准没有给出具体定义,因为它对于每个 UDT 都是唯一的,但您可能能够找到标准类型的规范。一些类似的容器是相对明显的——它们只是移动它们的内容,一个空的容器是一个定义明确的有效状态。基元不会修改移出的对象。

旁注:我相信T c = std::move(a)如果移动构造函数(或复制构造函数,如果没有提供移动)是显式的,则函数将失败。

于 2011-08-11T14:30:45.773 回答