Below is the most common implementation of std::swap
:
template<typename T>
void std::swap(T& a, T& b) {
auto tmp = std::move(a);
a = std::move(b);
b = std::move(tmp);
}
The C++ standard requires the time complexity of std::swap
must be constant. So, if a container type, such as std::vector
, std::list
, and the like, has correctly implemented its move-ctor & move-assignment-operator; then, it doesn't seem necessary to define a swap
member function for the type.
However, every container type in std
namespace has defined its own swap
member function, or a specialization of std::swap
. I think there must be a concrete rationale behind the design, what's that?
The rationale for the std::containers specialized swap is history:
In C++98/03, there was no move semantics. Copy only. But there was std::swap(x, y)
, which worked by copying. The std::containers could have used std::swap(x, y)
but it would have been very expensive: 1 copy construction and 2 copy assignments.
By implementing specialization, std::containers could just swap pointers and get an order of magnitude optimization, even without move semantics.
When C++11 came along (with move semantics), it didn't make sense to remove the specializations. Something would have broken somewhere. It was easier and safer just to upgrade the general swap
and and leave the specializations alone.
Bonus points: It turns out that the specializations are slightly faster than the general swap, but not greatly so. Maybe by a load/store or two. But the main reason is history.