【问题标题】:What can I do with a moved-from object?我可以用移出的对象做什么?
【发布时间】:2011-10-25 01:06:15
【问题描述】:

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

以标准库中定义的函数模板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));?)

【问题讨论】:

    标签: c++ c++11 variable-assignment swap move-semantics


    【解决方案1】:

    17.6.5.15 [lib.types.movedfrom]

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

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

    一般没有前置条件的操作示例:

    • 破坏
    • 作业
    • 常量观察者,例如getemptysize

    一般确实有前置条件的操作示例:

    • 取消引用
    • pop_back

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

    【讨论】:

    • 但是我可以像检查任何其他对象一样简单地检查先决条件,对吧?
    • @FredOverflow 当然,只要这些检查本身没有先决条件。
    • @Chris:但这与普通的、未移动的对象有何不同?
    • 可能应该是一个单独的问题,但这是否意味着:如果我有一个包含 char* buffer;int length; 成员的字符串,那么我的移动构造函数/赋值必须交换(或设置)两者的价值?或者,如果未指定长度(意味着 emptysize 返回无意义的值),是否可以?
    • @6502:你说的没有道理。 C++03 类不是“违反 C++0x 标准”,因为移动 ctor if generated 会违反标准。而且 C++03 代码不会移动该类,因此没有理由生成移动 ctor。
    【解决方案2】:

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

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

    【讨论】:

    • 并非所有它的成员函数都会表现出定义的行为。只有那些没有先决条件的人。例如,您可能不想将pop_backvector 移出。但是你当然可以查出是不是empty()
    • @Howard Hinnant: 来自空的vectorpop_back 从内存中无论如何都有未定义的行为,所以我很确定来自表现出未定义行为的移动向量的pop_back 是一致的。
    • 我们正在讨论移出对象。不是已知处于空状态的对象。移出对象具有未指定的状态(当然,除非另有说明)。 [lib.types.movedfrom]
    • @Howard 未指定,但有效,因此pop_back 的行为仍然与任何有效向量(甚至可能是空向量)一样。
    • 在这种情况下未指定和有效是什么意思?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-25
    • 2010-12-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多