Hello again!
And in this video, we are going to look at the default and delete keywords.
And yes, we are still talking about special member functions.
We have not suddenly started doing memory management.
We have seen that the compiler will sometimes synthesize special member functions. In modern C++,
the rules are more complicated, and it can be hard to work out what the compiler is doing.
So now we have the ability to force the compiler to synthesize a special menu function. And the syntax
for doing that is to put "= default" after the function's parameter list.
For example, if we have the default constructor and then we put equals default, that will force
the compiler to synthesize the default constructor, even if there are other constructors or a
copy constructor for the class.
If we put copy constructor equals default, that will force the compiler to synthesize a copy constructor,
which copies all the members. In modern C++, the compiler
may not always synthesize the copy constructor.
And similarly, with the assignment operator.
So we have a synthetic assignment operator which will assign all the members. And there are others. We
could put the destructor in there, but that does nothing anyway.
So it is a bit pointless.
If you can remember the first example in the video on copy elision, we had to provide a default
constructor because the compiler would not synthesize one.
That was because we had a copy constructor. So we actually wrote it out, but we could equally well
have put equals default.
And then the compiler will synthesize a constructor which default initializes all the members.
And that works exactly as it did before.
Why is this useful?
Well, you can look at the class definition and see immediately which special member functions the
class has implemented, or defined for it.
If you just let the compiler synthesize things, then you have to be able to work out what the compiler
has done, and that can take some effort.
It also documents that the programmer who wrote that class did actually want the default behaviour.
And it is not just the case that they forgot to implement it.
It avoids writing tedious code.
If you do have to implement the copying instructor because the compiler will not synthesize one, then
you have to write a member function, which copy initializes or assigns all the members.
With this, the compiler will do it for you.
And also, if the class definition changes, if we add or remove data members, then the compiler will
make sure that the member functions are always up to date.
Sometimes it is useful to have objects which cannot be copied. The traditional way to do this is to
make the copy constructor and the assignment operator private.
So for things like cout or cin, they cannot be copied because presumably the computer only
has one output and one keyboard!
So here is that code. If we do a copy operation, we expect to get a compile error. "Cannot access
private members declared in class Test".
And the same for the assignment operator.
So this works, but it is a bit of a hack, really.
And also, if you are looking through the code, you might miss that these are actually private.
In Modern C++, we can say that the copy constructor and the assignment operator are "= delete", so
they are deleted.
So again, this will give us an error.
But it is a different error this time. "Attempting to reference a deleted function. Function was explicitly
deleted". So you can see from looking at this, that these functions are not meant to be called.
And if we try to do an assignment, then we get the same result as well. Yes, "Attempting to reference
a deleted function".
So what does this actually mean? When we delete a function, it is still actually defined, but it
cannot be called.
And if you do try to call it, the compiler will give an error.
And this is different from default, which only applies to special functions. For a special member function,
it' i pretty easy for the compiler to guess what should be in there. If it is some other function than
the compiler has no idea at all.
With delete, any function can be deleted. So any member function or even non-member functions.
This can be useful sometimes if you want to prevent conversions or overloads from being caught.
But the main use is for copy constructors and assignment operators.
If you delete the default constructor, then you cannot default construct any objects.
And sometimes that can be useful as well.
If you want to force users of your class to call a constructor which takes arguments.
And then finally, one limitation on using the "=default". Sometimes the compiler cannot actually
synthesize the special member function.
The usual reason is that the class has a member which does not support that operation.
So that would be a member, which is another class.
And for example, it cannot be default constructed.
So if the member cannot be default constructed, then the compiler cannot synthesize your own default
constructor. Something that is a bit less obvious.
If the class has a member with a destructor which is deleted or inaccessible. So the destructor for
that class cannot be called, and that means you cannot destroy objects of that class.
And even for C++, creating objects which cannot be destroyed is probably a bit too far!
So that is not allowed.
So the result of all this is, if the compiler cannot synthesize the operation, then it will be synthesized
as "=delete".
So it will still be there, but you cannot call it.
Okay, so that is it for this video.
I will see you next time, but until then, keep coding!