在自我分配期间,复制和交换习语如何工作?

Posted

技术标签:

【中文标题】在自我分配期间,复制和交换习语如何工作?【英文标题】:How does the copy-and-swap idiom work during self-assignment? 【发布时间】:2011-04-26 07:57:06 【问题描述】:

我正在阅读优秀的copy-and-swap idiom 问题和答案。但是我没有得到一件事:在自我分配的情况下它是如何工作的?示例中提到的对象other 不会释放分配给mArray 的内存吗?那么被自赋值的对象不会有一个无效的指针吗?

【问题讨论】:

【参考方案1】:

但是我不明白的一件事是在自我分配的情况下它是如何工作的?

让我们看一个简单的案例:

class Container

    int*   mArray;
;

// Copy and swap
Container& operator=(Container const& rhs)

    Container   other(rhs);  // You make a copy of the rhs.
                             // This means you have done a deep copy of mArray

    other.swap(*this);       // This swaps the mArray pointer.
                             // So if rhs and *this are the same object it
                             // does not matter because other and *this are
                             // definitely not the same object.

    return *this;

通常您将上述实现为:

Container& operator=(Container other)
                       // ^^^^^^^^     Notice here the lack of `const &`
                       //              This means it is a pass by value parameter.
                       //              The copy was made implicitly as the parameter was passed. 

    other.swap(*this);

    return *this;

示例中提到的其他对象不会释放分配给 mArray 的内存吗?

该副本制作 mArray 的深层副本。 然后我们用 this.mArray 交换。当其他超出范围时,它会释放 mArray(如预期的那样),但这是它自己的唯一副本,因为我们在执行复制操作时进行了深层复制。

那么,自分配的对象最终不会有一个无效的指针吗?

没有。

【讨论】:

哎呀..我错过了复制ctor中的深层副本..感谢您的解释。 旧帖子,但我仍然有同样的疑问.. 与if (this == &other) return *this; 相比,在使用复制交换习语时进行自我分配的开销是不是太大了? @Hummingbird:在有自分配的情况下会有更多的开销。 BUT 自赋值极为罕见(在实际代码中非常小)。如果你反过来看。如果您正在优化代码以进行自分配,那么您正在对正常操作的代码感到失望。现在,正常操作是如此普遍,以至于它实际上可以产生可衡量的差异(人们已经做到了这一点)。我愿意在极少发生的情况下支付额外的成本,以在非常频繁发生的情况下获得最佳代码。

以上是关于在自我分配期间,复制和交换习语如何工作?的主要内容,如果未能解决你的问题,请参考以下文章

在可移动和不可复制的类上使用移动和交换习语是不是有意义

前端工程师面试自我介绍

自我介绍

Windows 上的应用程序在运行期间可以给自己改名(可以做 OTA 自我更新)

用强弱自我打破保留周期

在 Core Data 迁移期间添加关系 - 自我参考