繁体   English   中英

为什么在使用赋值运算符时使用复制和交换?

[英]Why do we use copy and swap when using assignment operator?

使用复制和交换方法时,我对赋值运算符有疑问。

String & operator = (String s) // the pass-by-value parameter serves as a temporary
{
   s.swap (*this); // Non-throwing swap
   return *this;
}// Old resources released when destructor of s is called.

假设我们有一个很好的复制构造函数,它可以深度复制所有指针和动态分配的变量。

那么,上面的代码和下面的代码有什么区别?

String & operator = (String s) // the pass-by-value parameter serves as a temporary
{
   return s;
}

因为我们有一个好的复制构造函数,所以我认为在operator =函数内部创建了另一个对象s。 那么,使用非抛出交换函数有什么意义呢?

主要区别在于第二个operator=根本不更改当前对象(即*this )。

String a, b;
b = a; // b is not changed at all

并请注意,第二个operator=通过引用返回s (退出函数时将被销毁),因此它只是一个悬挂的引用。


更笼统地说,我们使用复制和交换惯用法来提供强大的异常安全保证,这类似于提交或回滚语义; 如果操作由于异常而终止,则程序状态将保持不变。

String & operator = (String s) // Copy construct s. If exception happens here, 
                               // s won't be constructed, 
                               // and the state of the current object (*this) won't be changed
{
   s.swap (*this);             // Use non-throwing swap to commit the change
   return *this;               // Non-throwing operation
}

区别在于,在第二个代码块中,您将创建String对象的副本s ,返回对其的引用,然后该副本在作用域出口处被破坏,这将导致程序具有未定义的行为。

有几个主要区别:

赋值运算符应返回*this (并且几乎总是如此)。 这就是使链接分配成为可能的原因。

String s1, s2, s3;
s1 = s2 = s3; // Now all strings ave the same value.

而是,您返回对局部变量的引用。 然后,由于它没有指向有效的内存位置,因此成为悬挂的参考。

另外,赋值运算符必须更改分配的对象,这在您的代码中不会发生。

最后,为什么我们完全需要非抛出交换? 假设您的赋值运算符抛出异常。 分配失败后,分配对象的状态是什么?

某些实现可能导致对象处于无效状态,因为在更改对象的中间抛出了异常。

这就是交换发生的地方。由于交换从未抛出,因此我们可以确保分配的对象处于有效状态。 如果在交换之前引发异常,则该对象仍具有其旧值,如果在交换之后引发该对象,则其具有新值。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM