Hello again! In this video, we are going to look at the swap() function.
The C++ Library provides a standard swap() function.
This is a non-member function.
It takes two arguments of the same type, and it exchanges their internal data. swap() is declared as
noexcept, so it provides the "no throw" exception guarantee.
swap() is a generic function, so it knows nothing about the arguments.
It cannot do anything clever.
It just copies them.
However, there are overloads for library types and these do take advantage of the internal structure
of the arguments.
As an example, we looked at the string overload of swap(), earlier on in the course, and this just does
some pointer manipulation. And that is much faster than allocating memory and copying data.
There are some algorithms which exchange object data internally.
The sort() algorithm is one of those. It does that, to put the elements in order.
And there are some implementations which do that by calling the nonmember swap() function. And the function
which gets called depends on the element's type.
If there is an overload for the element, then that gets called.
Otherwise, the generic version is used, and that will copy the elements.
If you are writing your own class, and copying it takes a long time,
then this could be rather inefficient.
So if this is likely to happen, it could be worth implementing an overload of swap for your class.
So that is if the class is expensive to copy and you expect to do a lot of swap operations on it.
For example, if you have a container of these objects which get sorted.
So how do we do that?
The algorithm will assume that swap() is very fast, and does not throw any exceptions.
It is going to be a non-member function which will need access to data members.
So we need to make it a friend of the class, or perhaps delegate it to a public member function.
We are going to write it as an inline function, so the compiler can optimize away the function call.
I know that compiler writers say that their compilers are very clever and always do this, but in practice
they sometimes need a hint.
We are going to make it noexcept.
And then we are just going to call swap() for each data member.
We are going to use our String class again. Let's quickly remind ourselves what this does.
So we have two members.
We have a constructor which allocates memory.
We have a copy constructor which allocates memory and copies the data.
Then we have an assignment
operator, destructor, and then we declare our overload of swap as a friend of this class.
And here is our swap() definition is declared as in line and noexcept. We take the arguments by
reference, not by const reference, because we are going to modify them, and then we just call swap() for each
member of the class.
We have a main function, which creates two objects.
We print out their details, then we call swap(). And then we print out the details again.
So let's see if this works.
And there we are.
So we can see that we have the details before and after.
And we have just swapped around the size value and the pointers.
Let's see what happens if we comment out this swap overload.
So let's comment that out and then... this...
So what do you think will happen now?
We're going to call swap(), but there is no overload for this class.
So this is going to call the generic version, and that is going to copy the data.
So let's see what difference that makes.
Right, well, it looks as though this has made quite a bit of difference, we have all these operations
here, which are re-allocating memory.
And also we have different addresses, because they have been reallocated.
So you can see there is quite a lot more work involved in calling the generic version, which does copying.
So the overloaded version is much faster.
Okay, so that is it for this video.
I will see you next time.
But until then, keep coding!