For small ranges, std::sort
implementations in GCC’s stdlibc++ (and other standard library implementations) recurs to insertion sort for performance reasons (it’s faster than quicksort / introsort on small ranges).
GCC’s insertion sort implementation in turn doesn’t swap via std::swap
– instead, it moves whole ranges of values at a time, instead of swapping individually, thus potentially saving performance. The relevant part is here (bits/stl_algo.h:2187
, GCC 4.7.2):
typename iterator_traits<_RandomAccessIterator>::value_type
__val = _GLIBCXX_MOVE(*__i);
_GLIBCXX_MOVE_BACKWARD3(__first, __i, __i + 1);
*__first = _GLIBCXX_MOVE(__val);
_GLIBCXX_MOVE
is the same as std::move
from C++11 and _GLIBCXX_MOVE_BACKWARD3
is std::move_backward
– however, this is only the case if __GXX_EXPERIMENTAL_CXX0X__
is defined; if not, then these operations resort to copying instead of moving!
What this does is move the value at the current position (__i
) to a temporary storage, then move all previous values from __first
to __i
one up, and then re-insert the temporary value at __first
. So this performs n swaps in one operation instead having to move n values to a temporary location:
first i
+---+---+---+---+---+---+
| b | c | d | e | a | f |
+---+---+---+---+---+---+
|
<---------------+
first i
+---+---+---+---+---+---+
| --> b-> c-> d-> e-> f |
+---+---+---+---+---+---+
first i
+---+---+---+---+---+---+
| a | b | c | d | e | f |
+---+---+---+---+---+---+
^