std::sort does not always call std::swap

后端 未结 3 1316
独厮守ぢ
独厮守ぢ 2020-11-27 21:51

Consider the following code:

#include 
#include 
#include 

namespace my_space
{

struct A
{
    double  a;
           


        
3条回答
  •  南笙
    南笙 (楼主)
    2020-11-27 22:15

    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 |
    +---+---+---+---+---+---+
      ^
    

提交回复
热议问题