WEBVTT

00:00.210 --> 00:00.840
Hello again!

00:01.170 --> 00:05.910
In this video, we are going to look at using special member functions in C++ 11.

00:06.930 --> 00:13.890
As you may have noticed, the rules are a bit more complicated than they were before. Here is a table which

00:13.890 --> 00:16.680
was drawn up by the man who implemented move

00:16.680 --> 00:17.400
semantics.

00:18.540 --> 00:24.420
Let's have a look at that. And no, you are not expected to remember all this! In this video,

00:24.420 --> 00:28.920
I am going to try and give you some more practical guidelines on how to use special member functions.

00:31.530 --> 00:34.000
The first one is the "Rule of Zero".

00:34.620 --> 00:40.620
If your class does not need to implement a destructor, then it probably does not need to implement

00:40.620 --> 00:42.270
the copy operators either.

00:43.050 --> 00:47.460
So in this case you do not need to implement any special member functions at all.

00:48.000 --> 00:52.350
You can just leave the compiler to synthesise them for you, and they will do the right thing.

00:52.890 --> 00:55.650
And for the large majority of classes, this is quite sufficient.

00:57.550 --> 01:03.550
The compiler will also synthesize a default constructor, unless we define any constructor ourselves.

01:04.930 --> 01:10.510
If we have a constructor which takes arguments, sometimes it is useful to have a default constructor

01:10.900 --> 01:15.310
which will initialize the object with sensible values for the members.

01:18.950 --> 01:22.400
We have talked about the "Rule of Three" and the "Rule of Five".

01:23.120 --> 01:29.600
If your class implements a destructor, then it probably needs to implement the copy operators as well,

01:29.990 --> 01:33.470
because the ones that the compiler synthesizes will not do the correct thing.

01:34.640 --> 01:37.820
So they are not going to re-allocate memory or transfer the file handle.

01:39.800 --> 01:45.110
So in that case, you need to implement the destructor and also the copy constructor and copy assignment

01:45.110 --> 01:45.680
operator.

01:47.940 --> 01:52.110
And you'll probably need to implement a constructor, which will allocate the resource.

01:53.570 --> 01:57.140
In that case, the compiler will not synthesize any move operators.

01:58.100 --> 02:03.320
If copying your object involves a lot of work, and you have performance problems because of it,

02:03.860 --> 02:05.750
Then you can also add move operators.

02:06.410 --> 02:09.020
If you do not do that, then the copy operators will be used.

02:12.980 --> 02:14.840
We also talked about a move-only class.

02:15.320 --> 02:20.870
So this is in the situation where you need to declare a destructor, but you do not want to have duplicate

02:20.870 --> 02:22.910
objects managing the same resource.

02:23.750 --> 02:25.790
And in that case, you can make the class move-only.

02:26.270 --> 02:27.500
And we saw how to do that.

02:28.430 --> 02:33.890
We provided the move constructor and the move assignment operator, but not the copy operators.

02:35.360 --> 02:39.530
And in that case, the compiler will synthesize the copy operators as deleted.

02:40.340 --> 02:45.530
Or we can explicitly declare them as deleted ourselves, which is a bit clearer.

02:47.750 --> 02:50.840
And again, we may want to provide a constructor.

02:55.130 --> 02:57.370
It is possible to make an immoveable class.

02:57.380 --> 03:00.170
So this is a class which cannot be moved or copied.

03:00.920 --> 03:05.930
So objects of this class cannot be used as function arguments or returned from functions.

03:07.760 --> 03:10.280
There are some examples of this in the Concurrency Library.

03:10.970 --> 03:17.210
There are objects which will look a mutex when they are created, and then they unlock the mutex when

03:17.210 --> 03:17.900
they are destroyed.

03:18.530 --> 03:20.750
These are designed to be used within a single scope.

03:21.050 --> 03:25.850
So the idea is, when the program goes out of scope, the mutex is automatically unlocked.

03:26.780 --> 03:33.290
So the designers of the Concurrency Library have enforced this scope lifetime, by making it impossible

03:33.350 --> 03:37.070
to pass these to functions or return them from functions.

03:40.570 --> 03:42.670
To make an object immoveable,

03:42.760 --> 03:46.840
We delete the copy operators, and in that case, the compiler

03:46.840 --> 03:49.720
will not synthesize any move operators.

03:50.920 --> 03:57.100
If we try to copy or move the object, that will call the copy operators, and those are deleted, and we will

03:57.100 --> 03:58.090
get a compiler error.

04:00.480 --> 04:01.830
So here is an example.

04:02.190 --> 04:05.010
We have a class with deleted copy operators.

04:05.760 --> 04:12.690
We do not define any move operators. And in this case, the compiler is not going to synthesize any. So

04:12.690 --> 04:14.490
we can create an object of this class.

04:15.000 --> 04:17.070
But if we try to use the copy constructor,

04:19.700 --> 04:22.730
then we get the compiler error about deleted functions.

04:26.040 --> 04:32.400
And we also get that if we try to use the copy constructor. it is also possible, in theory, to make a

04:32.400 --> 04:34.410
class which can be copied, but not moved.

04:35.250 --> 04:41.010
To do that, we declare the move operators as deleted, and in that case the compiler will synthesize

04:41.370 --> 04:44.040
copy constructor and copy assignment operator.

04:46.350 --> 04:52.680
However, even though the move offices are deleted, the compiler can still decide that a move operator

04:52.680 --> 04:54.330
is the best match for a call.

04:55.080 --> 04:57.870
And then you get a compiler error when the function is called.

04:58.230 --> 05:03.300
For example, if you pass an rvalue, you may expect that this will fall back to the copy constructor,

05:03.750 --> 05:05.280
but in fact you get a compile error.

05:06.060 --> 05:09.570
So for that reason, using copy-only classes is not recommended.

05:11.660 --> 05:12.710
So let's try this out.

05:12.720 --> 05:19.250
So we have our copy operators, and we have the move operators declared as deleted.

05:20.660 --> 05:22.700
So if we call the copy constructor,

05:24.360 --> 05:32.700
we can do that. But if we try to pass an rvalue, then it does not fall back to the copy constructor.

05:33.120 --> 05:37.560
It tries to call the move operator, and then we get the compiler error again.

05:38.790 --> 05:41.340
So, copy-only objects are not very useful.

05:42.750 --> 05:44.220
Okay, so that is it for this feature.

05:44.730 --> 05:45.630
I will see you next time.

05:46.050 --> 05:47.940
But meanwhile, keep coding!
