我如何处理移出的物体?


138

该标准是否精确定义了对象从对象移出后可以做什么?我曾经认为,对移出的对象可以做的只是破坏它,但这还不够。

例如,采用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行呢?)

Answers:


53

移动的对象以未指定但有效的状态存在。这表明,尽管该对象可能无法再执行更多操作,但其所有成员函数仍应表现出已定义的行为-包括operator=-及其处于定义状态的所有成员,并且仍然需要销毁。该标准没有给出具体定义,因为它对于每个UDT都是唯一的,但是您可以找到标准类型的规范。一些类似的容器是相对明显的-它们只是移动内容,而空容器是定义良好的有效状态。基元不会修改移出的对象。

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


26
并非其所有成员函数都具有定义的行为。只有那些没有先决条件的人。例如,您可能不想pop_back迁移到vector。但是您当然可以找出是否存在empty()
Howard Hinnant

6
@Howard Hinnant:pop_back从空vector到内存,无论如何都具有未定义的行为,因此,我很确定pop_back从显示未定义的行为的移动矢量得出的结果是一致的。
小狗

12
我们正在讨论移出对象。没有已知对象处于空状态。移出的对象具有未指定的状态(除非另外指定,否则除外)。[lib.types.movedfrom]
霍华德·

5
@Howard未指定,但有效,因此pop_back在任何有效矢量上的行为仍像(甚至可能是空矢量)。
克里斯汀·劳

1
在这种情况下,未指定和有效的含义是什么?
Ankur S

114

17.6.5.15 [lib.types.movedfrom]

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

当对象处于未指定状态时,可以对没有先决条件的对象执行任何操作。如果存在要执行的前提条件操作,则无法直接执行该操作,因为您不知道对象的未指定状态是否满足前提条件。

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

  • 破坏
  • 分配
  • 常量观察员如getemptysize

通常具有前提条件的操作示例:

  • 取消引用
  • pop_back

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


1
但是我可以像检查其他任何对象一样简单地检查前提条件,对吗?
fredoverflow 2011年

6
@FredOverflow当然,只要这些检查本身没有任何先决条件。
Christian Rau

1
@Chris:但这与普通的非移动对象有何不同?
fredoverflow 2011年

2
可能应该是一个单独的问题,但这是否意味着:如果我有一个与char* buffer;int length;成员组成的字符串,那么我的move构造函数/赋值必须交换(或设置)两者的值?如果长度未指定(表示该长度emptysize返回无意义的值),还是可以的?
UncleBens 2011年

3
@ 6502:你没有道理。C ++ 03类不会“违反C ++ 0x标准”,因为生成的移动ctor 会违反该标准。而且C ++ 03代码不会移动该类,因此没有理由生成移动ctor。
MSalters 2011年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.