拷贝并交换惯用法在自我赋值时如何工作?

5

我正在阅读优秀的复制并交换惯用语问题和答案。但是有一件事情我没有理解:在自我赋值的情况下,它是如何工作的?在示例中提到的other对象不会释放分配给mArray的内存吗?因此,被自我赋值的对象最终会拥有一个无效指针吗?

1个回答

7
但是有一件事情我不太理解,对于自赋值的情况它是如何工作的呢?
让我们看一个简单的例子:
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进行交换,当other超出范围时,它会释放mArray(如预期),但这是其自己的唯一副本,因为在执行复制操作时我们进行了深度复制。
那么自我赋值的对象最终会有一个无效指针吗?
不会。

糟糕..我在复制构造函数中漏掉了深拷贝..感谢解释。 - Asha
1
旧帖子,但我仍然困惑不解...在使用复制交换惯用语时,对于自我赋值的情况,与if (this == &other) return *this;相比,这是否会产生过多的开销? - Hummingbird
3
@Hummingbird:在存在自赋值的情况下,会增加更多的开销。 但是,自赋值极为罕见(在实际代码中几乎不存在)。 如果你反过来看。 如果你为自赋值优化代码,那么你正在削弱正常操作的代码性能。 现在正常操作比自赋值要常见得多,它实际上可以产生可衡量的差异(人们已经测定过)。 我愿意在极为罕见的情况下支付额外的成本,以获得在相当频繁发生的最佳代码。 - Martin York

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接