Библиотека контейнеров Qt.
Здравствуйте уважаемые читатели, в этой статье мы с вами познакомимся с библиотекой контейнеров Qt, так же называемой Tulip. Она совместима с STL, но оптимизирована для использования классов Qt. Так же там предприняты оптимизации для препятствия раздувания кода шаблонов (насущная проблема С++). В основе Tulip лежат те же абстракции, что и в основе STL. Это контейнеры, итераторы и алгоритмы.
Контейнеры.
Контейнер это нечто, что мы можем использовать для хранения элементов других классов, а так же рассматривать как последовательность. Контейнеры делятся на две категории, и предъявляют определенные требования к объектам, которые в них хранятся.
Есть последовательные контейнеры, это коллекции в которых элементы упорядочены и занимают определенные позиции, к таким контейнерам относятся:
- QVector<T> - вектор
- QList<T> - список
- QLinkedList<T> - двусвязный список
- QQueue <T> - очередь
- QStack<T> - стек
Ассоциативные контейнеры это коллекции, в которых позиция элемента определяется значением элемента или его ключом.
- QHash<T> - хэш
- QMultiHash<T> - мульти хэш
- QMap<T> - словарь
- QMultiMap<T> - мульти словарь
- QSet<T> - множество
В таблице ниже приведены операции определенные во всех контейнерах.
| Метод (оператор) | Описание |
|---|---|
| empty(), isEmpty() | Вернет true если контейнер пуст |
| clear() | Очищает контейнер |
| insert() | Вставка в контейнер |
| remove() | Удаление из контейнера |
| size(), count() | Количество элементов в контейнере |
| begin() и constBegin() | Итераторы на начало контейнера |
| end() и constEnd() | Итераторы на конец контейнера |
| [] | Индексация отсутствует только в QSet<T> |
| = | Присваивание |
| == и != | Сравнение |
Все контейнеры предъявляют ряд требований к элементам хранящихся в них. Наличие конструктора по умолчанию обязательно. Копирующий конструктор и оператор присваивания то же должны быть. Если планируется сравнение контейнеров или используются ассоциативные контейнеры, требуются операторы сравнения и отношения. Так же для корректной работы контейнеров, желательно что бы типы используемые в виде элементов не генерировали исключений в деструкторах.
Нужно помнить, что QObject не имеет доступного конструктора копирования, поэтому в контейнерах нужно использовать только указатели на QObject.
Итераторы.
В терминах С++ итератор это некоторая абстракция которая позволяет обращаться с элементом на который он указывает как с указателем. Например для int[10] итератором может быть int*. Но не стоит путать итераторы с указателями. Нулевого итератора не бывает. Проверку итератора на действительность принято делать, сравнивая с концом последовательности на которую он указывает. Итератор считается действительным, если он указывает на какой ни будь элемент и через него можно получить доступ, к этому элементу используя селекторы доступа к членам (* и ->). Итератор может быть недействительным если:
- Он не был инициализирован
- Итератор указывает на контейнер, который явно или неявно изменил свои размеры
- Контейнер, на который он указывает уничтожен
- Итератор указывает на конец последовательности
Qt предоставляет два типа итераторов. Итераторы в стиле Java и итераторы в стиле STL. Мы программируем на С++, а значит рассмотрим только последние. В С++ итераторы делятся на три категории:
| Категория | Для записи | Для чтения | однонаправленный | двунаправленный | С произвольным доступом |
|---|---|---|---|---|---|
| Чтение | =*i | =*i | =*i | =*i | |
| Доступ | -> | -> | -> | -> [] | |
| Запись | *i= | *i= | *i= | *i= | |
| Итерация | ++ | ++ | ++ | ++ -- | ++ -- + - += -= |
| Сохранение | == != | == != | == != | == != < > <= >= |
*i = x; //Запись
x = *I; // Чтение
Вывести всю последовательность можно так:
QVector<int> vint;
for (QVector<int>::const_iterator i = vint.constBegin(); i != vint.constEnd(); ++i) {
qDebug()<<*i;
}
Алгоритмы.
Алгоритмы, как правило, выражаются функциями шаблонами и на входе принимают итераторы. Алгоритмы, возвращающие итераторы используют конец последовательности для сообщения о неудаче. Алгоритм возвращает итератор того же типа, что принял на входе, проверка диапазон не производится. Рассмотрим, например реализацию алгоритма STL find.
template <class Itor, class T> Itor find(Itor first, Itor last, const T& value)
{
while (first != last && *first != value)
++first;
return first;
}
Теперь мы можем использовать его например так:
QVector<int> vint;
QVector<int>::iterator i;
i = fild(vint.begin(),vint.end(),12);
if (i != vint.end())
qDebug()<<”Found! “<<*i;
В вашем распоряжении 60 алгоритмов STL и все алгоритмы Qt, за подробностями идем в мануал =) Помните средства STL объявлены в пространстве имен std. В следующих статьях мы начнем разбираться с контейнерами Qt и рассмотрим каждый из них.
Комментарии
Спасибо за хорошие статьи.
всё хорошо)тока вот про Java итераторы забыли,т.к они очень удобны в качестве добавление записей в контейнер)