std::swap is quite fundamental. And allow me to assume, fundamentally glanced over by you :) Which is a pity; understanding
std::swap concept fully, will make you more clear on a few other important C++ concepts.
Advice: to understand C++ swap one must be sure of the other C++ fundamentals fully. Please, if in doubt, stop reading and jump to the link provided in the text in bold font, for a quick refresh and then jump back.
The easy part
Swap is not Exchange
Exchange of values is the other fundamental and distinctive operation. The language you code in must allow you to clearly separate the fundamental operations. The key difference between swap and exchange is the lifetime of values swapped or exchanged.
Swap ( A , B ) // B life is over, it is a zombie. Do not deal with zombies
Exchange (A, B) // both B and A are alive and well, content exchanged
Caveat Emptor: here we use the word “exchange” as normal people do. In case you know or do not want to know about
std::exchange please see here.
Most importantly: B is said to be moved from after swap is done. (hint: yup, here is that link to the refresher, in bold ). So.
The move is a fundamental building block. The synopsis for
template < typename T>
void std::swap ( T & a, T & b )
// here the move ctor on temp is called
T temp = std::move( a ) ;
// the move assignment is used here
a = std::move( b );
// the move assignment is used here
b = std::move( temp );
That is a generic function. The use of
std::move assures first, move is conceptually implemented and executed and second, values are moved for all the types involved for arguments a and b above.
The swap concept is using the move concept. Move concept is the fundamental building block to value semantics of the to modern C++. Move is fundamental in making value semantics feasible. With the addition of “move constructor” and “move assignment”.
To understand and use for your own benefit the moving and swapping in C++ please always be aware of what type category, exactly is being moved or swapped. We will focus on the differences regarding the types of values moved or swapped.
In here we will peruse three particular categories of types to form the facets of the C++ moving/swapping. We will name them into three groups for this post:
- Fundamental Types
- User-Defined Trivial Types
- User-Defined Non-Trivial Types
There is a bit more to this whole subject. I might suggest you to start from here. Before proceeding please be sure you are clear on the C++ type system.
Swapping fundamental types
This type category is here as an natural and good starting point on the
std::swap journey of discovery. There is nothing surprising about swapping fundamental types.
// no surprises is a good news
int A = 2, B = 13 ;
// A is 13 and B is 2
The most important thing to notice here: B is moved from. C++ standard does mention that explicitly: Bi is in the “undefined state” after the move of its value to A. Remember: Swap is not Exchange.
You obviously can see it, B is actually alive and well, and equals 2, as you have expected. But keep in mind C++ is a language based on abstract thinking and abstractions. Thus the swap definition is carefully made so it applies to all the types of A and B above. Above just happens to be two integers. But please always have this mental picture
// T can be any complex type
// it happens in here it is constructible
// with number literals
T A = 2, B = 13 ;
// it also happens to be swappable
// with the inbuilt std::swap
// A is 13 and B is "undefined"!
That is actually standardized. It is very precisely defined what you can swap and what you can not swap. Any type T can be swapped as long as it is Swappable , which in code can be (and it is) checked with
std::is_swappable and friends.
And crucially there is always one left in the “undefined state” because it was “moved from” inside a swap operation. Now onto the next group of types.