该标准是否精确定义了对象移出后可以做什么?我以前以为可以对移出的对象进行破坏,但那还不够。例如,请使用标准库中定义的功能模板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);代替第1行中的T c(std::move(a));?)

#1 楼

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

侧面说明:我相信它是T c = std::move(a),因此,如果移动构造函数(如果未提供移动,则为复制构造函数)是显式的,该函数将失败。 br />

评论


并非其所有成员函数都会表现出已定义的行为。只有那些没有先决条件的人。例如,您可能不想pop_back从源移出的向量。但是您当然可以确定它是否为empty()。

– Howard Hinnant
2011年8月11日14:40

@Howard Hinnant:空向量的pop_back无论如何在内存中都具有未定义的行为,因此,我很确定,来自移动的向量的pop_back表现出未定义的行为是一致的。

–小狗
2011年8月11日14:50

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

– Howard Hinnant
2011年8月11日15:11

@Howard未指定,但有效,因此pop_back的行为仍类似于在任何有效向量上(甚至可能是空向量)。

–克里斯蒂安·劳(Christian Rau)
2011年8月11日15:15

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

– Ankur S
18年6月19日在12:41

#2 楼

17.6.5.15 [lib.types.movedfrom]


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


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

通常可以执行的操作示例没有先决条件:


销毁
分配
get,emptysize


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


取消引用
pop_back

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

评论


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

– fredoverflow
2011年8月11日15:17

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

–克里斯蒂安·劳(Christian Rau)
2011年8月11日15:18

@Chris:但是,这与普通的非移动对象有何不同?

– fredoverflow
2011年8月11日15:25

May-be应该是一个单独的问题,但这是否意味着:如果我有一个带有char *缓冲区的字符串;和int长度;成员,那么我的移动构造函数/赋值必须交换(或设置)两者的值?如果未指定长度(表示空值和大小返回无意义的值),还是可以的?

– UncleBens
2011年8月11日15:32

@ 6502:你没有道理。 C ++ 03类不会“违反C ++ 0x标准”,因为生成的移动ctor会违反该标准。而且C ++ 03代码不会移动该类,因此没有理由生成移动ctor。

– MSalters
11年8月12日在9:27