【问题标题】:Move semantics for big non-pointer base objects大型非指针基础对象的移动语义
【发布时间】:2013-05-20 03:43:55
【问题描述】:

当我阅读有关移动语义和右值引用的示例时,它们利用了右值引用的优势,并围绕包装指针 的大对象移动语义。 12

例如,他们只是复制移动对象内部的指针并将其设置为nullptr。 (移动/交换)

我的问题是,对于没有指针但它们很大的对象,移动语义是否有任何优势(性能)?

class BigClass
{
   int data[BIG_SIZE];
   int a01;
   .
   .
   . many members
   .
   .
   int z99;

public:

   move constructor ?!
};

【问题讨论】:

  • 是的。在移动操作之后,other 对象被(或应该)重置为 default 状态。
  • 不,就直接价值成员而言,这并没有真正的优势。
  • @CaptainObvlious 为什么要浪费时间将另一个对象更改为默认状态?该标准没有指定其他对象在移动操作后应该处于哪种状态。看到另一个对象(表面上)是一个临时对象,我能看到更改它的唯一原因是如果我们想利用它的析构函数来清理来自 *this 的资源(这通常通过交换另一个对象和 @987654326 来完成@)。
  • @Agentlien 不完全正确。标准确实规定对象必须处于可破坏状态。
  • @AndreKostur 当然,这是真的。在考虑了更多之后,我想说在移动构造函数中进行最小重置是好的,其中有必要确保析构函数做正确的事情并且不会释放其所有权应该被移动到目标实例的资源。在移动分配中,您需要交换此类成员。但是对于不拥有(智能)指针或类似资源处理程序的成员,重置似乎仍然是多余的。

标签: c++ c++11


【解决方案1】:

对于没有指针但它们很大的对象,移动语义是否有任何优势?

它在性能方面没有任何优势,因为您将无法快速“窃取”被移动对象的内脏,正如您所注意到的那样。

然而,从纯逻辑的角度来看,你的类的语义可能是这样的,你的对象不应该是可复制的,因此不能/不应该提供复制构造函数。

例如,unique_ptr 的内部不是任何可以移动得比复制更快的东西(它是原始指针上的零开销包装器),但是语义约束使得无法复制 @ 987654322@。在这种情况下,移动语义就是要保持这样的不变量,即只有 one unique_ptr 指向某个对象必须在您的程序中的某个时间存在。

因此,unique_ptr 的移动构造函数(或移动赋值运算符)也必须重置被移动的指针以保持不变量。

您的类可能与unique_ptr 完全不同,并且可能相当重,但仍可能存在使其不可复制的语义限制。在这种情况下,可以利用移动语义来强制执行正确的不变量。

【讨论】:

  • 关于不可复制类的要点。我以前问过自己这个问题,而这正是我找不到的答案。
  • @Agentlien:很高兴你发现它有帮助:)
  • 那么让我的BigClass 成为智能指针和 STL 的组合以具有移动语义优势会更好吗?
  • @MM.:您可以采用 pimpl 习惯用法,是的,这将同时进行异常安全和快速的移动 - 但需要您提供许多包装函数,这些函数什么都不做转发,并且会使内存访问模式更加稀疏。一如既往,这是一种工程妥协。您是否应该采用它取决于您的要求。另请注意,“STL”是一个错误的术语。您可能是指“来自 C++ 标准库的类型”:)
【解决方案2】:

由于每个对象都保留其所有数据的副本,并且没有要传输的指针,因此不可能进行浅拷贝,正如您所指出的。根据具体情况,将 other 对象设置回其默认状态可能是有意义的,但这是移动构造函数和复制构造函数之间唯一可能的区别。

【讨论】:

  • 从什么时候开始的?不需要移动构造函数来将要移动的对象设置为任何特定状态afaik
  • 没有。它不需要。移动的对象应该是可破坏和可分配的,但不需要重置(尽管这可能是一个好习惯)。举个极端的例子,从int 移动就像复制一样:源保持其状态。
  • 为什么将移动对象设置为默认状态是个好习惯?
  • 传达其状态已转移到移动到的对象。有人可能会提出这样的观点是浪费时间,但如果是这样的话,为什么在这种情况下有一个移动构造函数呢?除非移动构造函数的作用与复制构造函数不同,否则没有意义。
  • @slavik262 这正是 Andy Prowl 的回答所处理的并且回答得非常好。我个人认为,如果您窃取资源,您可能希望在两者之间交换它们。这将是移动构造函数中的重置(并且可以这样实现),并且在移动赋值中它让另一个对象的析构函数处理您移动到的对象当前持有的资源。
【解决方案3】:

在 SO 中随机冲浪,我发现了移动语义proposal。有一句话是我的回答:

对于 POD,移动和复制是相同的操作(一直到 机器指令级)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-06-09
    • 2016-09-22
    • 2011-02-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-16
    • 2023-02-09
    相关资源
    最近更新 更多