我可以对从中移动的对象执行哪些操作?

What can I do with a moved-from object?

提问人:fredoverflow 提问时间:8/11/2011 更新时间:10/25/2016 访问量:26172

问:

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

例如,采用标准库中定义的函数模板: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 行将失败。那么,我还能对从中移动的对象做什么呢?我究竟在哪里可以找到标准中的这些详细信息?

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

C++ C++11 变量赋值 交换 语义

评论


答:

65赞 Puppy 8/11/2011 #1

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

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

评论

29赞 Howard Hinnant 8/11/2011
并非所有成员函数都会表现出定义的行为。只有那些没有先决条件的人。例如,您可能不想从 .但你当然可以找出它是否是.pop_backvectorempty()
7赞 Puppy 8/11/2011
@Howard Hinnant:无论如何,从空有未定义的行为,从记忆中,所以我很确定从移动的向量表现出未定义的行为是一致的。pop_backvectorpop_back
14赞 Howard Hinnant 8/11/2011
我们正在讨论从对象中移动。不是已知处于空状态的对象。移出对象具有未指定的状态(当然,除非另有指定)。[lib.types.movedfrom]
6赞 Christian Rau 8/11/2011
@Howard 未指定,但有效,因此仍然像在任何有效向量上一样(甚至可能是空向量)。pop_back
1赞 Ankur S 6/19/2018
在这种情况下,未指定和有效是什么意思?
144赞 Howard Hinnant 8/11/2011 #2

17.6.5.15 [lib.types.movedfrom]

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

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

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

  • 破坏
  • 分配
  • 常量观察者,例如 , ,getemptysize

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

  • 引用
  • pop_back

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

评论

6赞 Christian Rau 8/11/2011
@FredOverflow 当然,只要这些检查本身没有先决条件。
2赞 fredoverflow 8/11/2011
@Chris:但是,这与普通的、没有移动的物体有什么不同呢?
2赞 Howard Hinnant 8/11/2011
@FredOverflow:唯一的区别是大多数操作使对象处于指定状态。moved-from 状态未指定,但除此之外,并不特殊。当然,如果你是你的类的作者,你可以自由地使你的移动状态变得像你想要的那样特别。但要知道,如果您在 std 算法中使用您的类,则您的类型需要满足 std 算法的规定要求,无论是否处于 moved-from 状态([utility.arg.requirements],表 20 和 22)。
2赞 UncleBens 8/11/2011
也许应该是一个单独的问题,但这是否意味着:如果我有一个带有 and members 的字符串,那么我的移动构造函数/赋值必须交换(或设置)两者的值?或者,如果长度未指定(意味着并返回无意义的值)可以吗?char* buffer;int length;emptysize
4赞 MSalters 8/12/2011
@6502:你说不通。C++03 类不会“违反 C++0x 标准”,因为如果生成移动 ctor,则会违反标准。C++03 代码不会移动该类,因此没有理由生成移动 ctor。