WEBVTT

00:00.730 --> 00:06.490
Hello again! In this video, we are going to look at synthesised member functions. So, as we have already

00:06.490 --> 00:07.060
touched on,

00:07.510 --> 00:13.150
if you do not define certain special member functions, the compiler will synthesize them for you.

00:14.140 --> 00:18.670
So this is the constructor, the copy constructor and the assignment operator.

00:19.720 --> 00:24.910
There are also some new special member functions in modern C++ related to move operations.

00:25.390 --> 00:27.490
And we are going to look at those later on in the course.

00:28.450 --> 00:30.250
And finally, the destructor.

00:34.850 --> 00:42.740
There are rules for when the compiler will synthesize these. In traditional C++, older C++ before 2011,

00:43.070 --> 00:49.220
the compiler will always fill in the missing special functions. If we do not define a constructor or a

00:49.220 --> 00:54.470
copy constructor - because the copy constructor is regarded as a special kind of constructor - then the

00:54.470 --> 00:57.050
compiler will synthesize a default constructor.

00:57.530 --> 01:02.120
This takes no arguments, and it calls the default constructor for each data member.

01:02.840 --> 01:07.340
So if the data member is built in, that will be default initialized, which means undefined.

01:09.250 --> 01:14.380
If there is no copy constructor, the compiler will synthesize one, and this will just call the copy

01:14.380 --> 01:18.940
constructor for each data member. If there is no assignment operator,

01:18.940 --> 01:24.730
similarly, the compiler will synthesize one which calls the assignment operator for each data member

01:24.730 --> 01:25.330
of the class.

01:26.440 --> 01:32.530
And finally, if there is no destructor, the compiler will synthesize one. And that does nothing because

01:32.530 --> 01:35.290
the destructors for the members are automatically called.

01:41.060 --> 01:44.570
In modern C++, the rules are much more complex.

01:44.900 --> 01:47.690
There is five special member functions instead of three.

01:48.230 --> 01:54.610
And the rules about whether some special functions are synthesized depends on whether some of the other

01:54.620 --> 01:56.180
special member functions are defined.

01:57.140 --> 01:58.640
So we are going to leave that for now.

01:58.940 --> 02:02.240
We will come back to this in the section where we look at move operations,

02:02.240 --> 02:03.050
move semantics.

02:06.750 --> 02:12.210
So here's an example of how the compiler will synthesize these special member functions.

02:12.960 --> 02:20.040
We have our "pet" test class with an int and a string member, but we do not define any special functions, just

02:20.040 --> 02:24.330
this print member function, which is going to display the values of the members.

02:26.310 --> 02:32.490
So there is no constructor or copy constructor, so the compiler will synthesize a default constructor,

02:33.060 --> 02:36.870
and this will just use the default initialization for the data members.

02:38.260 --> 02:42.780
There is no copy constructor, so the compiler will synthesize one, which we have seen before.

02:43.350 --> 02:46.020
It will just initialize the members from the argument.

02:47.010 --> 02:51.390
If there is no assignment operator, then again, well, we have seen that.

02:51.930 --> 02:53.970
And finally, the destructor will do nothing.

02:58.530 --> 03:03.410
So we have a couple of test objects which we default construct, then we have one which we copy

03:03.430 --> 03:03.950
construct.

03:04.710 --> 03:09.030
Then we do an assignment. And we print out the data after each step.

03:12.920 --> 03:16.040
So again, we have these weird undefined values.

03:16.460 --> 03:20.840
The string's default constructor just creates an empty string, so that is not too bad.

03:20.920 --> 03:23.150
But this is really weird.

03:27.330 --> 03:31.920
Let's try and make this look a bit better. So let's add a constructor, which takes some arguments.

03:41.690 --> 03:44.510
So we are going to initialize the members from these arguments.

03:46.980 --> 03:48.740
Then we do not need to do anything else.

03:50.390 --> 03:54.560
And then we can give these some sensible initial values.

04:05.310 --> 04:10.290
So we initialize them with a string literal. We could just use a character string, but we might as well get used

04:10.350 --> 04:15.600
to using the newer versions. And let's see what we get now.

04:16.800 --> 04:17.460
So that's better.

04:18.600 --> 04:23.310
(So that is not actually.. The, er...) The output is slightly wrong. That is not the default constructor anymore.

04:23.580 --> 04:26.220
That is now calling the constructor, which takes these arguments.

04:27.330 --> 04:29.960
So "i" is 5 and "str" is "Hello".

04:30.900 --> 04:33.030
And then test2 has 7 and "Goodbye".

04:34.750 --> 04:41.530
And test3 is the same as test. And then we overwrite test with test2, so we get 7 and

04:41.530 --> 04:41.860
"Goodbye".

04:43.750 --> 04:50.050
This ability of the compiler to synthesize special member functions is quite useful. If we have a class

04:50.050 --> 04:56.470
and we do not need the constructor, destructor, et cetera, to do anything special, then we can just

04:56.470 --> 05:01.870
leave them. And the compiler will automatically provide ones which do the right thing.

05:02.320 --> 05:08.290
On the other hand, if we do need to implement them and we do not implement them, the compiler will

05:08.290 --> 05:10.030
not give us an error or a warning.

05:10.360 --> 05:13.630
Instead, it will replace them with ones which do the wrong thing.

05:14.740 --> 05:19.960
For example, if we have members which are built-in types, they will be default initialized and we

05:19.960 --> 05:20.980
will get the wrong values.

05:21.880 --> 05:28.960
If we have a member which is a pointer to allocated memory or a resource handle, then the compiler's

05:29.140 --> 05:34.540
copy constructor and assignment operator will perform what is known as a "shallow" copy.

05:34.960 --> 05:38.620
So this means they just overwrite the data in the target object.

05:42.130 --> 05:48.310
In this case, we need to provide the functions ourselves to make sure that the correct operations are

05:48.310 --> 05:48.850
performed.

05:49.090 --> 05:54.850
If we need the built-in types to have correct default values, we need to provide a default constructor which will

05:54.850 --> 06:03.580
initialize them. If we need to perform a so-called "deep copy", which will allocates new memory, obtained

06:03.580 --> 06:09.490
a new resource for the target object and then initialize it with the same data as the source object.

06:10.030 --> 06:13.570
Then we need to implement the copy constructor and the assignment operator.

06:14.710 --> 06:17.800
We are going to look at shallow and deep copying in more depth.

06:19.000 --> 06:21.730
(Get it? Deep copy? Depth? Never mind!)

06:22.450 --> 06:25.590
We are going to look at that in more detail in the next video.

06:25.660 --> 06:27.430
But until then, keep coding!
