C++ 如何处理从对象移动的对象?

C++ 如何处理从对象移动的对象?,c++,c++11,variable-assignment,swap,move-semantics,C++,C++11,Variable Assignment,Swap,Move Semantics,标准是否精确定义了我可以在对象从中移动后对其执行的操作?我曾经认为,对一个从对象中移出的对象所能做的就是销毁它,但这是不够的 例如,以标准库中定义的函数模板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!

标准是否精确定义了我可以在对象从中移动后对其执行的操作?我曾经认为,对一个从对象中移出的对象所能做的就是销毁它,但这是不够的

例如,以标准库中定义的函数模板
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!
}
模板
无效掉期(T&a、T&b)
{
tc=std::move(a);//第1行
a=std::move(b);//第2行:从对象移动的赋值!
b=std::move(c);//第3行:从对象移动的赋值!
}
显然,必须能够指定给从对象移动的对象,否则第2行和第3行将失败。那么,对于从对象中移动的对象,我还能做些什么呢?我在标准中的具体位置可以找到这些详细信息


(顺便问一下,为什么它是
tc=std::move(a);
而不是
tc(std::move(a));
在第1行?

从对象中移动的对象处于未指定但有效的状态。这表明,虽然对象可能不再能够做很多事情,但其所有成员函数仍应表现出已定义的行为(包括
操作符=
)及其处于已定义状态的所有成员,并且仍然需要销毁。该标准没有给出具体的定义,因为它对于每个UDT都是唯一的,但是您可以找到标准类型的规范。有些容器是比较明显的,它们只是移动内容,空容器是定义良好的有效状态。基本体不会修改“从中移动”对象


旁注:我相信它是
tc=std::move(a)
,因此如果move构造函数(或者如果没有提供move,则复制构造函数)是显式的,那么函数将失败。

17.6.5.15[lib.types.movedfrom]

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

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

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

  • 毁灭
  • 分配
  • 常量观察器,如
    get
    empty
    size
通常具有先决条件的操作示例:

  • 解引用
  • 弹回

这个答案现在以视频格式显示在这里:

不是所有的成员函数都会表现出定义的行为。只有那些没有先决条件的。例如,您可能不想从
向量
中移动的
返回
。但是你当然可以发现它是否是空的。
empty()。不是已知处于空状态的对象。从对象移动的对象具有未指定的状态(当然,除非另有指定)。[lib.types.movedfrom]@Howard未指定,但有效,因此
pop_back
的行为仍然类似于任何有效向量(甚至可能是空向量)。未指定和有效在本文中是什么意思?但我可以像检查任何其他对象一样简单地检查前提条件,对吗?@fredwolflow,当然,只要这些检查本身没有前提条件。@Chris:但这与正常的、未从对象中移动的有什么区别?可能应该是一个单独的问题,但这是否意味着:如果我有一个带有
char*buffer的字符串
整数长度成员,那么我的移动构造函数/赋值必须交换(或设置)两者的值?或者,如果长度未指定(意味着
为空
大小
返回无意义的值),是否可以?@6502:你没有意义。C++03类没有“违反C++0x标准”,因为如果生成一个move-ctor,就会违反该标准。C++03代码不会移动该类,因此没有理由生成移动向量。