WEBVTT

00:01.020 --> 00:06.960
Hello again! In this video, we are going to have an overview of the assignment operator. The assignment

00:06.960 --> 00:08.520
operator is a member function.

00:08.520 --> 00:10.620
It is called "operator equals".

00:11.430 --> 00:18.060
The assignment operator is automatically called when we assign to existing objects of the same class.

00:18.660 --> 00:25.440
So if we have y = z, and y and z are both objects of class Test, for example.

00:27.400 --> 00:34.030
It is a member function, so it is called on the object on the left of the equals sign, and the object

00:34.030 --> 00:36.640
on the right is passed as the argument to the call.

00:37.180 --> 00:42.010
So this will actually be called as, y dot operator equals, with argument

00:42.040 --> 00:42.370
z.

00:44.560 --> 00:50.860
After the statement has been executed, the members of y, the data members, will have the same values

00:50.860 --> 00:54.790
as the data members in z. And z will be unmodified, of course.

00:56.440 --> 01:03.520
The assignment operator takes its argument z by const reference, and it returns the modified object

01:03.820 --> 01:07.540
so y equals z will return the new value of y.

01:09.750 --> 01:14.940
The reason for returning a value is that we can do multiple assignments in C++.

01:15.480 --> 01:21.210
We are allowed to "chain" operators. And we have already used that when we are outputting several variables

01:21.210 --> 01:22.170
in a single statement.

01:22.500 --> 01:24.780
We chain the left shift operators.

01:26.670 --> 01:29.070
So we can say x equals y equals z.

01:29.430 --> 01:33.300
So x and z will then have the same values as z.

01:34.710 --> 01:37.220
This is processed from right to left.

01:37.260 --> 01:39.450
So it starts by doing y equals z.

01:40.530 --> 01:43.330
So that will call y dot operator equals, with argument

01:43.330 --> 01:43.350
z.

01:44.370 --> 01:46.590
And this will return the new value of y.

01:48.060 --> 01:52.980
Then the new value of y is used as the argument to the next assignment.

01:53.460 --> 01:56.520
So X equals the new value for it.

01:57.360 --> 02:03.980
So this will actually be called as x dot operator equals, and the argument will be the result of y dot operator

02:04.140 --> 02:10.440
equals with argument z, and then the members of x and y will have the same values as z.

02:13.570 --> 02:16.510
The assignment operator actually returns by reference.

02:17.890 --> 02:22.470
That may sound a bit dangerous, but it is actually safe, because it is a reference to the object that

02:22.510 --> 02:27.670
the member function is called on. And that object will still be valid after the member function returns.

02:28.870 --> 02:33.220
You will find some sources which say it should be a const reference, but that is not correct.

02:34.210 --> 02:40.300
It is legal to modify the return value from an assignment, and there are occasions, very rare, when you want

02:40.300 --> 02:40.870
to do that.

02:42.160 --> 02:46.360
In particular, the standard library containers require that you are able to modify it.

02:47.230 --> 02:53.830
If you try to store an object in a container and the assignment operator returns a const reference instead

02:53.830 --> 02:57.190
of a modifiable reference, the code will not compile.

02:58.710 --> 03:04.530
So the correct signature for the assignment operator is operation equals, a member of the class Test.

03:05.370 --> 03:13.170
It will take a Test object by reference to const, and it will return a modifiable reference to a Test object.

03:18.740 --> 03:22.460
So how do you get a reference to the object?

03:23.210 --> 03:29.090
Well, the operator is a member function, so when it is called, it will be given an extra hidden argument,

03:29.090 --> 03:35.090
which is a pointer called "this". And "this" is a pointer to the object that the member function was called

03:35.090 --> 03:35.270
on.

03:36.110 --> 03:42.530
So if we dereference the "this" pointer, after we perform the assignments, then we will get the modified

03:42.530 --> 03:43.010
object.

03:44.570 --> 03:50.330
If we return star this, then we are returning the object. And the compiler will make sure that it is returned

03:50.330 --> 03:56.000
by reference, because the function says it's to be returned by reference. The compiler will handle that bit

03:56.000 --> 03:56.180
for us.

03:59.840 --> 04:05.000
So the rules for when you write an assignment operator are pretty similar to the rules for writing

04:05.000 --> 04:05.960
a copy constructor.

04:06.350 --> 04:07.820
Normally you do not need to bother.

04:08.350 --> 04:13.100
The compiler will synthesize one which calls the assignment operator of all the data members of the

04:13.100 --> 04:13.490
class.

04:14.210 --> 04:15.770
And usually, that is going to be good enough.

04:17.950 --> 04:22.150
There are situations in which that is not going to give the correct behaviour.

04:22.390 --> 04:25.000
And in that case, you do need to write an assignment operator.

04:25.660 --> 04:28.120
And again, it is when the class manages a resource.

04:28.600 --> 04:32.710
But the reasons are slightly different. With an assignment operator,

04:32.740 --> 04:37.300
we have two objects which are already set up and have their own resources.

04:38.170 --> 04:44.560
If we just copy the resource from one class over the resource in the other class, then the original resource

04:44.560 --> 04:45.040
is lost.

04:45.430 --> 04:51.190
For example, if we are dealing with allocated memory and we have a pointer to the memory, if we overwrite

04:51.190 --> 04:57.400
the pointer in the target object, then that pointer is now lost. The original value of the pointer.

04:57.880 --> 05:03.760
So that means we can no longer find the memory, and in particular, we cannot release the memory. So

05:03.790 --> 05:06.280
that memory is still going to be in use, but not available.

05:06.520 --> 05:07.930
So that is a memory leak.

05:08.680 --> 05:14.050
And similarly, with a file handler or a database connection, the handle or the connection is still

05:14.050 --> 05:16.150
in use, but it is no longer available.

05:18.440 --> 05:23.090
The correct way to handle this is to write an assignment operator, and the assignment operator will

05:23.150 --> 05:25.700
release the resource before doing the assignment.

05:26.240 --> 05:30.740
And then when it does the assignment, it will get its own copy of the resource. Which has the same

05:30.740 --> 05:33.620
data as the one that it is being assigned from.

05:34.280 --> 05:39.200
So in effect, this has the same effect as calling the destructor and then calling the copy constructor.

05:39.650 --> 05:44.700
Calling the destructor would release the resource, and calling the copy constructor

05:44.700 --> 05:49.910
would give the target object a new resource, but it has the same values as the one that it is being

05:49.910 --> 05:50.600
assigned from.

05:54.800 --> 05:58.100
As an example of a synthesized assignment operator.

05:58.550 --> 06:03.940
So this is the kind of code that the compiler will generate if we do not do anything. For our class

06:03.950 --> 06:04.370
Test,

06:05.060 --> 06:10.640
we have the assignment operator signature. And then it will just assign the members.

06:11.030 --> 06:14.450
So "i" will be assigned from the "i" value in the argument.

06:15.200 --> 06:18.170
The string will be assigned from the string member in the argument.

06:18.890 --> 06:25.190
And then we dereference the object that we are called on, and we return it, and the compiler will return

06:25.190 --> 06:26.210
that by reference.

06:28.300 --> 06:34.150
So let's add an assignment operator to our String class with a capital "S". We do not actually need one

06:34.150 --> 06:39.250
at the moment, but it will be good practice to get used to writing assignment operators.

06:39.520 --> 06:42.100
And we will need one when we make the class more realistic.

06:43.630 --> 06:49.720
So this is the signature. We have operator equals, which takes a const reference to an object of

06:49.720 --> 06:52.900
the class, and it returns an object by reference.

06:53.800 --> 06:55.060
Then we assign the members.

06:55.450 --> 07:03.070
So this will actually call the assignment operator of the string class and then we get the object

07:03.070 --> 07:09.400
that we were called on, and we return that. And the rest of the code is almost the same.

07:10.030 --> 07:15.430
We have a String object, but this time we are going to assign it to it, instead of copy creating it.

07:16.870 --> 07:20.350
In fact, one thing we should do in here is to add a default constructor.

07:21.010 --> 07:27.190
So this is a default constructor which takes no arguments, and it is just going to initialize the member

07:27.190 --> 07:28.870
string as an empty string.

07:32.120 --> 07:34.220
So we can actually make that an empty string...

07:54.030 --> 07:59.910
OK, so we have our string with "world", then we have a string with "bang". We assigned "world" to it, and

07:59.910 --> 08:02.250
now the string's data is "world".

08:02.790 --> 08:06.650
And then we have an empty string, and we assign "world" to that.

08:06.660 --> 08:09.240
And the data in the string is now "world".

08:10.200 --> 08:11.190
OK, so that all works.

08:11.970 --> 08:13.560
So that is it for this video.

08:14.010 --> 08:14.910
I will see you next time.

08:14.910 --> 08:17.400
But until then, keep coding!
