STL

std::sort vs qSort: что выбрать для сортировки в C++/Qt?

обновлено 73 просмотров

Введение

В старом коде на Qt часто встречается функция qSort, а в современных примерах — std::sort. Что выбрать для сортировки в C++/Qt и почему код с qSort перестаёт собираться после перехода на Qt 6? В этой статье разберём вопрос std::sort vs qSort, разберём, как заменить все устаревшие алгоритмы Qt на стандартные, и покажем, на что обратить внимание при миграции.

Что такое qSort

В Qt 4 и Qt 5 был собственный набор алгоритмов в заголовке <QtAlgorithms>: qSort, qStableSort, qLowerBound, qBinaryFind, qFind, qCopy и другие. Их добавили в то время, когда стандартная библиотека C++ поддерживалась компиляторами по-разному. В Qt 5 эти функции объявили устаревшими и рекомендовали использовать алгоритмы STL. В Qt 6 их удалили окончательно.

std::sort vs qSort: сравнение

std::sortqSort
Заголовок<algorithm><QtAlgorithms>
СтатусЧасть стандарта C++Устарел в Qt 5, удалён в Qt 6
КонтейнерыЛюбые с итераторами произвольного доступа: std::vector, std::array, QList, массивыКонтейнеры Qt и STL
СложностьГарантированно O(n log n) с C++11O(n log n) в среднем
СтабильностьНет (для стабильной — std::stable_sort)Нет (для стабильной — qStableSort)
constexprС C++20Нет
Параллельная версияС C++17 (политики выполнения)Нет
Сравнение std::sort и qSort

Пример: одна и та же сортировка

#include <QList>
#include <algorithm>

QList<int> list = {5, 3, 8, 1};

// Устаревший вариант (Qt 4/5)
// qSort(list.begin(), list.end());

// Современный вариант
std::sort(list.begin(), list.end());   // 1 3 5 8

Синтаксис почти не отличается, поэтому замена обычно сводится к поиску и замене по проекту.

Таблица замены устаревших алгоритмов Qt

Устаревший QtЗамена из STL
qSort(begin, end)std::sort(begin, end)
qSort(container)std::sort(container.begin(), container.end())
qStableSortstd::stable_sort
qLess<T>()std::less<T>()
qGreater<T>()std::greater<T>()
qLowerBound / qUpperBoundstd::lower_bound / std::upper_bound
qBinaryFindstd::lower_bound с проверкой результата
qFindstd::find
qCopystd::copy
qFillstd::fill
qCountstd::count
Замена алгоритмов QtAlgorithms

Обратите внимание на вариант qSort(container), принимавший контейнер целиком. У std::sort такой перегрузки нет, но в C++20 есть std::ranges::sort(container).

Сортировка по убыванию

#include <functional>

// Было
// qSort(list.begin(), list.end(), qGreater<int>());

// Стало
std::sort(list.begin(), list.end(), std::greater<int>());

// Или лямбдой
std::sort(list.begin(), list.end(), [](int a, int b) { return a > b; });

Как найти устаревший код в проекте

Компилятор поможет найти все проблемные места. Определите в файле проекта макрос, который превращает использование устаревших API в ошибки:

# qmake
DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x050F00
# CMake
target_compile_definitions(myapp PRIVATE QT_DISABLE_DEPRECATED_BEFORE=0x050F00)

С этим макросом все функции, объявленные устаревшими до Qt 5.15, перестанут компилироваться ещё в Qt 5. Это удобный способ подготовить проект к переходу на Qt 6 заранее.

Что выбрать

  • В новом коде используйте только std::sort и другие алгоритмы STL.
  • Если важен порядок равных элементов, берите std::stable_sort.
  • В старом проекте замените qSort до перехода на Qt 6: так миграция пройдёт спокойнее.
  • Для C++20 и новее присмотритесь к std::ranges::sort с проекциями.

Заключение

Выбор между std::sort и qSort сегодня очевиден: qSort удалён в Qt 6, а std::sort работает со всеми контейнерами Qt и даёт гарантированную производительность. Замена почти механическая и выполняется по таблице выше. Подробнее о возможностях стандартной сортировки читайте в статье Использование std::sort в C++, а о сортировке строк и структур в QList — в статье сортировка QList.