QT 4: программирование GUI на С++
Шрифт:
Последовательные контейнеры
Вектор QVector<T> представляет собой структуру данных, в которой элементы содержатся в соседних участках оперативной памяти. Вектор отличается от обычного массива С++ тем, что знает свой собственный размер и этот размер может быть изменен. Добавление элементов в конец вектора выполняется достаточно эффективно, но добавление элементов в начало вектора или вставка в его середину могут быть неэффективны.
Рис. 11.1. Вектор чисел двойной точности.
Если
Ниже та же самая задача решается путем объявления пустого вектора и применения функции append, которая добавляет элементы в конец вектора:
Вместо append можно использовать оператор <<:
Организовать цикл просмотра элементов вектора можно при помощи оператора [ ] и функции count:
Элементы вектора, которым не было присвоено какое-нибудь значение явным образом, инициализируются при помощи стандартного конструктора класса элемента. Основные типы и указатели инициализируются нулевым значением.
Вставка элементов в начало или в середину вектора QVector<T>, а также удаление элементов из этих позиций могут быть неэффективны для больших векторов. По этой причине Qt предлагает связанный список QLinkedList<T> — структуру данных, элементы которой располагаются не в соседних участках памяти. В отличие от векторов, связанные списки не поддерживают произвольный доступ к элементам, но обеспечивают «константное время» выполнения операций вставки и удаления.
Рис. 11.2. Связанный список значений типа double.
Связанные списки не обеспечивают оператор [ ], поэтому необходимо использовать итераторы для прохода по всем элементам. Итераторы также используются для указания позиции элементов. Например, в следующем фрагменте программного кода выполняется вставка строки «Tote Hosen» между «Clash» и «Ramones»:
Более подробно итераторы будут рассмотрены позже в данном разделе.
Последовательный контейнер QList<T> является «массивом—списком», который сочетает
в одном классе наиболее важные преимущества QVector<T> и QLinkedList<T>. Он поддерживает произвольный доступ, и его интерфейс основан на индексировании подобно применяемому векторами QVector. Вставка в конец или удаление последнего элемента списка QList<T> выполняется очень быстро, а вставка в середину выполняется быстро для списков, содержащих до одной тысячи элементов. Если не требуется вставлять элементы в середину больших списков и не нужно, чтобы элементы списка занимали последовательные адреса памяти, то QList<T> обычно будет наиболее подходящим контейнером общего назначения.Класс QStringList является подклассом QList<QString>, который широко используется в программном интерфейсе Qt. Кроме наследуемых от базового класса функций он имеет несколько дополнительных функций, увеличивающих возможности класса по обработке строк. Класс QStringList будет обсуждаться в последнем разделе этой главы.
QStack<T> и QQueue<T> — еще два примера удобных подклассов: QStack<T> — это вектор, для работы с которым предусмотрены функции push, pop и top. QQueue<T> — это список, для работы с которым предусмотрены функции enqueue, dequeue и head.
Во всех до сих пор рассмотренных контейнерах тип элемента T может являться базовым типом (например, int или double), указателем или классом, который имеет стандартный конструктор (т.е. конструктор без аргументов), конструктор копирования и оператор присваивания. К таким классам относятся QByteArray, QDateTime, QRegExp, QString и QVariant. Этим свойством не обладают классы Qt, которые наследуют QObject, поскольку последний не имеет конструктора копирования и оператора присваивания. На практике это не составляет проблему, потому что мы можем просто хранить в контейнере указатели на такие типы данных, а не сами объекты QObject.
Тип T также может быть контейнером; в этом случае следует иметь в виду, что необходимо разделять рядом стоящие угловые скобки пробелами, в противном случае компилятор будет сбит с толку, воспринимая >> как оператор. Например:
Кроме только что упомянутых типов в качестве типа элементов контейнера может задаваться любой пользовательский класс, отвечающий описанным ранее критериям. Ниже дается пример такого класса: