简体   繁体   中英

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

I have a question about assignment operator when using copy-and-swap method.

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.

Let's suppose we have a good copy constructor which deep-copy all the pointers and dynamic allocated variables.

Then, what's the difference between above code and below code?

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

Since, we have a good copy constructor, I think another object, s, is created inside the operator= function. So, what's the point of using non-throwing swap function?

The main difference is that the 2nd operator= doesn't change the current object (ie *this ) at all.

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

And note the 2nd operator= is returning s (which will be destroyed when get out of the function) by reference, so it'll be just a dangled reference.


To be more general, we use copy & swap idiom to provide strong exception safety guarantee, which is something like commit-or-rollback semantics; If an operation terminates because of an exception, program state will remain unchanged.

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 ,返回对其的引用,然后该副本在作用域出口处被破坏,这将导致程序具有未定义的行为。

There are several main differences:

An assignment operator should return *this (and almost always does). This is what makes chaining assignments possible.

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

Instead, you return a reference to a local variable. It then becomes a dangling reference, since it doesn't point to a valid memory location.

Also, the assignment operator must change the assigned object, which doesn't happen in your code.

And finally, why do we need the non-throwing swap at all? Let's assume your assignment operator throws an exception. What is the state of the assigned object after the failed assignment?

Some implementations might cause the object to be in an invalid state, since the exception was thrown in the middle of changing it.

This is where the swap comes in. Since, the swap never throws, we can be sure the assigned object is in a valid state. If an exception is thrown before the swap, the object still has its old value, and if it was after the swap, the object has its new value.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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