Чому своп викликається std :: sor, лише якщо мій контейнер містить більше 32 елементів?


13

Привіт, у мене просте запитання:

class A 
{
public:
    A(int);
    A(const A&);
    A& operator=(const A&);
    ~A();
private:
    int* ptr_;

    friend bool operator<(const A&, const A&);
    friend void swap(A&, A&);
};

A::A(int x) : 
    ptr_(new int(x))
{}

A::A(const A& rhs) :
    ptr_(rhs.ptr_ ? new int(*rhs.ptr_) : nullptr)
{}

A& A::operator = (const A & rhs)
{
    int* tmp = rhs.ptr_ ? new int(*rhs.ptr_) : nullptr;
    delete ptr_;
    ptr_ = tmp;

    return *this;
}

A::~A()
{
    delete ptr_;
}

bool operator<(const A& lhs, const A& rhs)
{
    cout << "operator<(const A&, const A&)" << endl;
    return *lhs.ptr_ < *rhs.ptr_;
}

void swap(A& lhs, A& rhs)
{
    cout << "swap(A&, A&)" << endl;
    using std::swap;
    swap(lhs.ptr_, rhs.ptr_);
}

int main()
{

    std::vector<A> v{ 33,32,31,30,29,28,27,26,25,24,23,22, 21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5, 4,3,2,1 };
    std::sort(v.begin(), v.end());

}

Сорт має більше 32 елементів swap. З 32 елементами або менше, елементи все ще сортуються, але swapне називаються.

  • Я використовую MSVC ++ 2019 на x64.
  • Коли swapвикликається і коли це не так і чому? Дякую!
  • Я не використовував swapпри призначенні копії лише розрізнення виклику до нього від сортування від оператора присвоєння копії.

6
std::sortвдається до сортування вставки, якщо кількість елементів становить 32 або менше, і використовує швидке сортування в іншому випадку.
Evg

@Evg Це вимога чи це пояснення цього конкретного контексту?
Франсуа

2
@ FrançoisAndrieux, це детальна інформація про впровадження стандартної бібліотеки Microsoft. Я здогадуюсь, що це причина поведінки, яку спостерігає ОП. Зараз я переглядаю вихідний код, щоб отримати більше деталей.
Evg

1
Відповідна частина джерела: while (_ISORT_MAX < (_Count = _Last - _First) && 0 < _Ideal)там, де _ISORT_MAXзадано значення 32. Рядок 3447 <algorithm>використання VS 16.5.0
ChrisMM

Жоден справжній кваксор не використовується в жодних сучасних стандартних бібліотеках будь-якими мовами. Усі користуються модифікованими змішаними версіями, які є лише хитким стилем, коли кількість елементів досить велика. Наприклад, Java та Python використовують Timsort, тоді як .NET Framework та бібліотека C ++ GCC використовують Introsort . libstdc ++ і libc ++ також використовують сортування вставки для коротких послідовностей. Дивіться, які алгоритми використовуються в C ++ 11 std :: сортування в різних реалізаціях STL?
phuclv

Відповіді:


14

std::sortРеалізація Microsoft виглядає приблизно так:

const int ISORT_MAX = 32;  // maximum size for insertion sort

template<class RanIt, class Diff, class Pr>
void Sort(RanIt First, RanIt Last, Diff Ideal, Pr Pred)
{
    Diff Count;
    for (; ISORT_MAX < (Count = Last - First) && 0 < Ideal; )
    {   // divide and conquer by quicksort
        pair<RanIt, RanIt> Mid = Unguarded_partition(First, Last, Pred);

        // ...
    }

    if (ISORT_MAX < Count)
    {   // heap sort if too many divisions
        Make_heap(First, Last, Pred);
        Sort_heap(First, Last, Pred);
    }
    else if (1 < Count)
        Insertion_sort(First, Last, Pred);  // small
}

Коли діапазон для сортування має 32 елементи або менше, Sortвикористовується сортування вставки. Сортування вставки не використовується swapпри його здійсненні . В іншому випадку використовується швидке сортування "ділити і перемагай". Під час реалізації він викликає iter_swap(всередині Unguarded_partition), який, у свою чергу, викликає swap:

template<class FwdIt1, class FwdIt2>
void iter_swap(FwdIt1 Left, FwdIt2 Right)
{   // swap *Left and *Right
    swap(*Left, *Right);
}

Все це деталі реалізації. Вони відрізняються від однієї стандартної бібліотечної реалізації до іншої.


1
libcxx використовує сортування вставок для послідовностей довжиною менше 6 або 30 залежно від типу. libstd ++ робить це для послідовностей з 16 елементів або менше. Які алгоритми використовуються в C ++ 11 std :: сортування в різних реалізаціях STL?
phuclv
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.