Библиотека контейнеров 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*. Но не стоит путать итераторы с указателями. Нулевого итератора не бывает. Проверку итератора на действительность принято делать, сравнивая с концом последовательности на которую он указывает. Итератор считается действительным, если он указывает на какой ни будь элемент и через него можно получить доступ, к этому элементу используя селекторы доступа к членам (* и ->). Итератор может быть недействительным если:
  1. Он не был инициализирован
  2. Итератор указывает на контейнер, который явно или неявно изменил свои размеры
  3. Контейнер, на который он указывает уничтожен
  4. Итератор указывает на конец последовательности

    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 и рассмотрим каждый из них.



Добавлена: 08-03-2009 | Изменена: 10-03-2009 | Пользователем: gnudimarik | Просмотров: 1842

Комментарии

wing 07-12-2009 14:42
Спасибо за хорошие статьи.
Но уж слишком много ошибок орфографических :-(
Chexov 13-12-2009 00:38
всё хорошо)тока вот про  Java итераторы забыли,т.к они очень удобны в качестве добавление записей в контейнер)


Оставить комментарий



Капча *

Captcha

Комментарий будет опубликован после проверки модератором

Для подсветки синтаксиса исходный код следует обрамлять следующими тэгами
<pre><code class="синтаксис" >код</code></pre>
Подерживаются следующие: cpp php javascript sql html-xml css ini