Урок №4. Контейнеры в Qt5

  Дмитрий Бушуев  | 

  |

  Обновл. 16 Сен 2021  | 

 42781

 ǀ   12 

Библиотека контейнеров Qt5 является универсальной коллекцией шаблонов классов и алгоритмов, позволяющих программистам легко реализовывать общие структуры данных, такие как очереди, списки и стеки.

Контейнеры в Qt5

Контейнеры — это классы общего назначения, которые хранят в себе значения заданного типа. В языке С++ имеется свой набор контейнеров, который называется STL.

Стоит отметить, что идеологии контейнеров Qt и STL, при всей своей схожести, отличаются в следующем:

   Фреймворк Qt5 предоставляет максимально богатый интерфейс, а копирование контейнера происходит за константное время, но цена этому — дополнительные проверки при доступе к разделяемым данным (implicit data sharing).

   В свою очередь, STL предоставляет ограниченный интерфейс и следует идеологии уменьшения необоснованного расхода процессорного времени, памяти, ненужной нагрузки и пр.

Мы же, программируя на Qt, можем использовать как Qt-контейнеры, так и STL. Если вы не знакомы с STL или предпочитаете работать «только с Qt», то можете использовать классы Qt вместо классов STL.

На этом уроке мы рассмотрим следующие контейнеры:

   QVector;

   QList;

   QStringList;

   QSet;

   QMap.

Есть 2 типа контейнеров:

   Последовательные — элементы хранятся друг за другом (последовательно). Примерами последовательных контейнеров являются QList, QVector, QLinkedList.

   Ассоциативные — элементы хранятся в виде пары ключ-значение. Примерами ассоциативных контейнеров являются QMap и QHash.

Контейнер QVector


QVector — это шаблонный класс, который представляет динамический массив. Данный контейнер хранит свои элементы в соседних участках памяти, а доступ к ним осуществляется при помощи индексов. Для векторов с большим количеством элементов вставка значений в начало или в середину вектора может происходить довольно медленно, потому что это может сопровождаться перемещением большого количества элементов в памяти на одну позицию, поэтому в подобных случаях рекомендуется использовать QList вместо QVector.

Следующий пример показывает работу с вектором, элементами которого являются целые числа:

Результат выполнения программы:


Контейнер QList

QList — это контейнер, который предназначен для создания списка элементов. QList во многом похож на QVector. Он хранит список значений указанного типа и обеспечивает быстрый доступ к ним с помощью индексов, а также вставку и удаление элементов. Это один из наиболее часто используемых контейнеров в Qt.

Пример использования контейнера QList:

Результат выполнения программы:


Контейнер QStringList


QStringList — это контейнер, который предоставляет список строк. Он удобен прежде всего тем, что имеет дополнительные методы для фильтрации данных и легко взаимодействует со стандартными компонентами Qt, «понимающими» строки QString. Он также поддерживает быстрый доступ к элементам, их вставку и удаление.

В следующем примере мы создадим список строк из исходной строки и выведем их на экран:

Результат выполнения программы:


Контейнер QSet

QSet предоставляет однозначный (без повторений) математический набор с возможностью быстрого поиска элементов. Значения хранятся в неопределенном порядке.

В следующем примере QSet используется для хранения значений цветов. Как уже было сказано, данный контейнер является однозначным, поэтому нет смысла указывать одно и то же значение цвета несколько раз:

Результат выполнения программы:


Контейнер QMap


QMap — это ассоциативный массив (словарь), который хранит пары ключ-значение. Он обеспечивает быстрый поиск значения, ассоциированного с ключом. В следующем примере у нас есть два словаря, в которых мы сопоставляем ключ в виде строки целочисленному значению:

Результат выполнения программы:


Сортировка пользовательских классов

В следующем примере мы выполним сортировку объектов пользовательского класса в QList.

Ниже представлен заголовочный файл book.h для нашего пользовательского класса Book (книга):

А здесь реализация класса Book (у нас есть два геттеры для доступа к элементам класса):

Далее мы создадим несколько объектов класса Book и отсортируем их с помощью алгоритма std::sort():

CompareByTitle() — это функция сравнения, используемая алгоритмом сортировки:

Алгоритм std:: sort() сортирует книги в списке по заголовку:

Результат выполнения программы:

На этом всё! До следующего урока.

Оценить статью:

Звёзд: 1Звёзд: 2Звёзд: 3Звёзд: 4Звёзд: 5 (66 оценок, среднее: 4,97 из 5)
Загрузка...

Комментариев: 12

  1. Andrew:

    Чисто для лучшего познания QSet контейнера. При каждой компиляции компонент brown до сортировки помещается в разные позиции контейнера, то есть он может быть в 0 месте, может в 1 и так далее. Чем это можно объяснить?

    1. Денис Фролов:

      Существуют неупорядоченные контейнеры, которые не гарантируют определённую позицию элемента в себе. Не помню с чем это связано, но вроде за счёт этого они быстрее предоставляют доступ к своему содержимому. По факту QSet просто для других целей, если нужен порядок следует использовать QVector или QList.

  2. Александр:

    И несколько не по теме.
    Роман Льва Николаевича Толстого "Война и мiр" на современном языке — это "Война и общество". Таким образом: "War and society".

    1. Фото аватара Юрий:

      Интересное замечание, но сейчас официальным переводом является именно "War and Peace". Если официально примут название "War and Society", тогда можно будет менять, а пока в статье всё ок))

  3. Георгий:

    Здравствуйте! Было бы неплохо чуть подробнее описать когда правильнее использовать контейнеры stl, когда Qt.

    1. Кирилл:

      Есть правило: "When in Rome… Do as the Romans Do".
      Если вы работаете с Qt лучше использовать Qt контейнеры.
      Например , подумайте, что будет если вам надо будет передать
      данные в функцию Qt. Вам придётся писать код по преобразованию stl контейнеров в Qt контейнеры и наоборот.
      Больше информации тут.
      https://stackoverflow.com/questions/1668259/stl-or-qt-containers

  4. Дмитрий:

    Спасибо за уроки и за урок в частности.

  5. Юрий:

    Небольшое замечание по поводу QList. В уроке указано следующее по поводу QList:"Он хранит список значений указанного типа и обеспечивает быстрый доступ к ним с помощью индексов, а также быстрые вставку и удаление элементов."
    В документации же на qt (ссылка https://doc.qt.io/qt-5/qlist.html#details от 26.11.2019) написано " It stores items in a list that provides fast index-based access and index-based insertions and removals.", что можно перевести как " Он хранит элементы в списке, который обеспечивает быстрый доступ по индексу и, основанные на индексах, вставку и удаление." Быстрой вставки и удаления в произвольное место QList не обеспечивает потому, что он представляет собой массив, в котором содержатся ссылки на хранимые в нем объекты. Согласно статье "Container Class" (https://doc.qt.io/qt-5/containers.html#algorithmic-complexity от 26.11.2019) сложность вставки для QList соответствует O(n), что соответствует сложности вставки для QVector.
    В Qt5 объект, который обеспечивает "быструю" (сложностью O(1)) вставку и/или удаление в произвольное место обеспечивает контейнер QLinkedList.

    1. Фото аватара Дмитрий Бушуев:

      Спасибо за замечание. В ближайшее время внесем в статью соответствующие правки. 🙂

    2. Фото аватара Юрий:

      Исправили)

  6. IAmInLoveWithC:

    Классный урок !!!

    1. Фото аватара Дмитрий Бушуев:

      Спасибо 🙂

Добавить комментарий для Александр Отменить ответ

Ваш E-mail не будет опубликован. Обязательные поля помечены *