WEBVTT

00:00.180 --> 00:03.750
Hello again! In this video, we are going to look at "copy and swap".

00:05.380 --> 00:09.340
Copy and swap is another way to write an assignment operator for a class.

00:10.270 --> 00:15.700
We create a local variable in the function body, which is a copy of the function argument.

00:16.690 --> 00:23.230
We swap the contents of this local variable with the object that we are assigning to, the "this" object

00:23.470 --> 00:25.360
or the object that "this" points to.

00:26.680 --> 00:33.940
Then we can return this object, which now contains the assigned-to values. And when we return from

00:33.940 --> 00:36.520
the function, this local variable is destroyed.

00:39.730 --> 00:40.930
So let's break this down.

00:41.200 --> 00:43.810
We start off by calling the copy constructor.

00:44.260 --> 00:46.960
We pass the function argument to the copy constructor.

00:47.980 --> 00:49.450
This could throw an exception.

00:49.870 --> 00:53.290
If it does, then the destructors will be called for this scope.

00:53.710 --> 00:58.330
The "temp" object will be destroyed. Then the function returns immediately.

00:59.200 --> 01:01.530
The object we are assigning to is not modified.

01:01.540 --> 01:03.100
We have not done anything to it yet.

01:03.940 --> 01:08.890
And there is an exception for the caller to handle, which is normal when a constructor throws an exception.

01:12.140 --> 01:19.340
If the constructor does not throw an exception, then this "temp" object now contains the values that we want to assign

01:19.340 --> 01:20.840
to the "this" object.

01:21.530 --> 01:26.030
So we just swap them around, we swap the data from the "temp" object and the "this" object.

01:29.590 --> 01:33.040
swap() is noexcept, so this cannot throw any exceptions.

01:33.730 --> 01:39.940
When this returns, "this" will have the data from the function argument and "temp" will have the data that

01:39.940 --> 01:41.800
used to be in the "this" object.

01:46.090 --> 01:50.140
And then finally, we have the right values in "this", so we return it.

01:50.530 --> 01:56.020
So the usual way to return from assignment operators, we dereference the "this" pointer and the compiler

01:56.020 --> 01:57.640
converts it to a reference.

01:58.850 --> 02:04.400
Then when the function returns, the destructors are called, the "temp" object is destroyed, and that will

02:04.460 --> 02:08.120
release all the resources that the original object was using.

02:08.720 --> 02:10.700
So there are no memory leaks in this code.

02:12.870 --> 02:14.160
So let's look at this.

02:14.430 --> 02:17.970
So we have our String class again. The the rest of the class is exactly the same.

02:20.180 --> 02:27.860
Here is our assignment operator, which performs a "copy and swap". There is the copy and there is the swap.

02:28.850 --> 02:34.970
and then we return the object after it has been assigned to. And when the function returns, the local

02:34.970 --> 02:36.650
variable will be destroyed.

02:41.280 --> 02:46.170
In the main function, we create a couple of objects and call the copy constructor and the assignment

02:46.170 --> 02:46.680
operator.

02:49.490 --> 02:56.720
So we have these two objects. Then we call the copy constructor. Then we call the assignment operator.

02:56.900 --> 03:01.970
"a" is going to be "this" inside the assignment operator, and "c" is going to be the argument.

03:05.730 --> 03:06.240
In here.

03:08.130 --> 03:09.540
Then we make a copy of "c".

03:10.050 --> 03:16.530
Then we swap the data between "a" and the copy of "c", and then we return the modified version of "a".

03:17.790 --> 03:21.990
And the copy of "c", which has "a"'s old data, is now destroyed.

03:23.280 --> 03:28.410
So when we call the assignment operator, that calls the copy constructor, to make a copy of "c". Then we

03:28.410 --> 03:31.170
call swap() and then the destructor is called.

03:32.280 --> 03:40.200
So that is the old address of "a" that gets released. And then when we return, "a" has a new memory allocation.

03:42.860 --> 03:45.240
So that is the "copy and swap" idiom.

03:45.890 --> 03:48.560
The advantages of this are, that it is easy to work with.

03:48.980 --> 03:55.340
You do not need to check for self-assignment, because "this" and "temp" must be distinct objects, so they cannot

03:55.430 --> 03:56.330
interfere with each other.

03:57.230 --> 04:03.170
We are re-using code from the copy constructor and the destructor, instead of replicating that code in

04:03.170 --> 04:04.130
the function body.

04:05.440 --> 04:09.100
The code is much shorter, which means there are less things for us to get wrong.

04:10.090 --> 04:13.240
And in the traditional implementation, there are quite a lot of things to get wrong!

04:15.110 --> 04:20.450
The disadvantages are: this always allocates memory. With the traditional implementation, you can check

04:20.450 --> 04:25.430
the size, and you only need to reallocate if the existing buffer is too small.

04:26.180 --> 04:30.110
If the current buffer is large enough, you can just re-use it.

04:30.680 --> 04:33.890
So that is an optimization which you cannot do with copy and swap.

04:34.520 --> 04:40.070
The other disadvantage is that this creates an extra object, so it can use more memory than the traditional

04:40.220 --> 04:40.760
assignment

04:40.760 --> 04:41.300
operator.

04:43.340 --> 04:49.790
In terms of exception safety, copy and swap provides the strong exception guarantee, and you do not

04:49.790 --> 04:51.560
need to do very much work to get it!

04:52.910 --> 04:57.380
If an exception occurs while initializing the new object, we do not do the swap.

04:57.980 --> 05:04.400
Instead, we destroy the new object, the local object. And the original object is left unmodified.

05:05.330 --> 05:09.020
The program is in the same state as when the assignment operation began.

05:09.950 --> 05:11.420
Okay, so that is it for this feature.

05:11.930 --> 05:15.050
I will see you next time, but until then, keep coding!
