【问题标题】:What are the operations supported after an object is moved? [duplicate]对象移动后支持哪些操作? [复制]
【发布时间】:2014-03-22 21:24:07
【问题描述】:

如果一个对象实际被移动到另一个位置,那么在原始对象上支持哪些操作?

为了详细说明,我有一个类型 T 和可用的移动构造函数。用以下语句

T x{constructor-args};
T y{std::move(x)};

对象x 可以做什么(假设对象实际上使用T 的可用移动构造函数从x 移动到y)?

具体来说,

  • x 肯定可以销毁。我可以假设x 在移动后很容易被破坏吗?
  • 可以将x 分配或移动分配给一个新对象(我猜是的,因为我看到很多swap 使用它)?
  • 我可以构造一个新的对象对象来代替x吗?如果有任何机会允许这样做,那么是否有可能有一个 uninitialized_move 与(部分)重叠的源和目标范围一起使用,例如 std::copy 而不像 std::uninitialized_copy

    T z{some-args};
    x = z; //or x = std::move(z);
    T u{some-args};
    new(&x) T{std::move(u)}; // or new(&x) T{u}; etc
    

【问题讨论】:

    标签: c++ c++11 move-semantics


    【解决方案1】:

    无论你定义它是什么。至少,结果 对象应该是可破坏的——它的析构函数是 调用,并且对象的状态应该是这样的 不会引起任何问题。

    标准库保证它的对象是一些 相干状态。您可以调用任何成员函数:它是 未指定您得到的回报,结果将是 连贯:如果您在已移动的向量上调用size, 您也可以使用小于该值的索引调用operator[]size 返回(但在唯一合理的实现中, size 将返回 0,)。这可能比现在更多 然而,需要有效使用;所有这一切都是真正必要的 是调用析构函数会起作用。

    为了更清楚,以std::vector 为例:如果我们 假设通常的实现,带有三个指针,开始, end 和 limit (或者无论如何它们被称为:limit 意味着 一过去分配的内存结束,所以capacity() 返回limit - begin)。搬家后标准 要求所有三个指针都为空。多数情况 实现中,将不会访问限制指针 析构函数,因此可删除的宽松要求将 如果仅将开始和结束指针设置为 null,则可以满足。

    【讨论】:

    • 所以,我假设允许分配(复制和移动),而不是放置构造。然后,假设给定三个指针,顺序为 p1,p2,p3,其中 [p1,p2) 是原始内存,[p2,p3) 包含一些 T 类型的对象,在 [p1 范围内移动它们的最佳方法是什么? ,p1+(p3-p2)) ?我的猜测是,uninitialized_copymove_iterator 是行不通的,因为某些对象可能会在移动位置上移动构造。
    • @abir 你想复制它们,还是移动它们? (但我不确定你的问题是什么。)
    • 将 [p2,p3) 上的对象向后移动几个位置,从 p1 开始。所以我想,我必须分别根据原始内存 [p1,p2) 和包含移动对象 [p2,p3+p1-p2) 的内存来组合 uninitialized_movemove
    【解决方案2】:

    关于库类型,标准说 (17.6.5.15)

    除非另有说明,否则此类移出的对象应置于有效但未指定的状态。

    这意味着它们至少应该是可破坏和可分配的。正如 James 在下面提到的,对象仍应符合其自己的接口。您自己的类型应该遵循相同的想法。

    您不应该对这种事情使用placement-new。假装移动构造函数不存在,并以与以前相同的方式编写代码,使用 operator=。您示例中的最后一行应为x=std::move(u);x=u;

    【讨论】:

    • 它的意义远不止于此。例如,std::vector 的有效但未指定状态意味着如果v 已被移动,您仍然可以调用v.size()for ( size_t i = 0; i != v.size(); ++ i ) v[i]; 必须仍然有效,并且v.push_back( something ); 必须工作。在实践中,如果你也支持销毁,那么支持这一点对于 std::vector 来说并没有显着增加,但对于更复杂的类型,它可能会有所作为。
    • 你说得对,但我说的是对明智的移动操作员的最一般要求。
    • 是的。这正是我的观点。最一般的要求低于标准对其自身类型的要求。
    猜你喜欢
    • 1970-01-01
    • 2011-12-13
    • 1970-01-01
    • 1970-01-01
    • 2016-04-30
    • 1970-01-01
    • 2022-06-30
    • 2019-04-25
    • 2017-04-29
    相关资源
    最近更新 更多