Топ контрибуторов
loading
loading
Знаете ли Вы, что

После прохождения теста можно комментировать вопросы теста, а Ваши комментарии увидят модераторы теста и пользователи, которым когда-либо эти вопросы попадались.

Лента обновлений
ссылка Oct 22 23:24
Комментарий от alexcei88:
В вопросе переменная s даже не выводиться, а выводитьс...
ссылка Oct 22 17:46
Комментарий от AlexFurm:
Это UB, так можно вызывать только статические функции ч...
ссылка Oct 22 17:43
Комментарий от AlexFurm:
Любые битовые операции с signed это UB
ссылка Oct 21 20:30
Комментарий от yoori:
Любой вариант скомпилируется если компилировать не в конеч...
ссылка Oct 21 16:53
Добавлен вопрос в тест QA (Quality Assurance)
Статистика

Тестов: 153, вопросов: 8596. Пройдено: 443367 / 2177508.

Qt. Контейнеры. Часть 1

head tail Статья
категория
C++
дата28.09.2012
авторSemenovMS
голосов6

Библиотека Qt предоставляет набор контейнерных классов общего назначения основанных на шаблонах. Эти классы могут использоваться для хранения элементов определенного типа. Например, если вам необходим массив изменяемого размера, содержащий QString, используйте QVector<QString>.

Эти контейнерные классы разработаны для легкого, безопасного и простого использования вместо контейнеров STL. Если вы не знакомы с STL, или предпочитаете работать "только с Qt", то можете использовать эти классы вместо классов STL.

Контейнерные классы - классы с неявным совместным использованием данных, они реентерабельны, и они оптимизированы для быстрой работы, низкого потребления памяти и минимального увеличения кода (inline), результат в меньшем исполняемом файле. Кроме того, они потоко-безопасны в ситуациях, где они используются, как контейнеры только для чтения, всеми потоками используемыми для доступа к ним.

Для обхода элементов, хранящихся в контейнере, вы можете использовать один из двух типов итераторов: итераторы в стиле Java и итераторы в стиле STL. Итераторы в стиле Java легче использовать и они предоставляют высокоуровневую функциональность, тогда как итераторы в стиле STL немного более эффективны и могут быть использованы вместе с базовыми алгоритмами Qt и STL.

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

     Контейнерные классы

Qt предоставляет следующие контейнерные классы:

     QList<T>

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

Элементы могут быть добавлены в любой из двух концов списка используя QList::append() и QList::prepend(), или они могут быть вставлены в середину используя QList::insert(). QList наиболее оптимизированный, чем другие классы-контейнеры, чтобы развертываться в настолько маленький код насколько это возможно в исполняемом файле. QStringList унаследован от QList<QString>.

     QLinkedList<T>

Подобен QList, за исключением того, что он используется итераторами для доступа к элементам чаще, чем целочисленные индексы. Он также обеспечивает лучшую эффективность, чем QList, когда вставляются элементы в середину большого списка, и имеет хорошую семантику итераторов. (Итераторы, указывающие на элемент в QLinkedList, остаются действительными, до тех пор пока существует элемент, в то время, как итераторы QList могут стать недействительными после вставки или удаления.)

     QVector<T>

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

     QStack<T>

Это вспомогательный подкласс QVector, реализующий семантику "последним пришел, первым ушел" (LIFO). Он добавляет к уже присутствующим в QVector следующие функции: push(), pop() и top().

     QQueue<T>

Это вспомогательный подкласс QList, реализующий семантику "первым пришел, первым ушел" (FIFO). Он добавляет к уже присутствующим в QList следующие функции: enqueue(), dequeue() и head().

     QSet<T>

Предоставляет однозначное математическое множество с возможностью быстрого просмотра.

     QMap<Key, T>

Предоставляет словарь (ассоциативное множество), который хранит соответствия ключей типа Key и значений типа T. QMap хранит данные, упорядоченные по ключу; если порядок не имеет значения, то класс QHash работает быстрее.

     QMultiMap<Key, T>

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

     QHash<Key, T>

Имеет почти такой же API, как и QMap, но предоставляет значительно более быстрый поиск. QHash хранит свои данные в произвольном порядке.

     QMultiHash<Key, T>

Это вспомогательный подкласс от QHash, который предоставляет удобный интерфейс для многосвязной хэш-таблицы.

Контейнеры могут быть вложенными. Например, вполне возможно использовать QMap<QString, QList<int> >, где типом ключа является QString, а типом значения - QList<int>. Единственный нюанс - это то, что вы должны оставить пространство между закрывающими угловыми скобками (>); иначе, компилятор C++ воспримет два символа > как оператор сдвига вправо (>>) и сообщит об ошибке.

Контейнеры определены в индивидуальных заголовочных файлах с тем же именем, что и контейнер (например, <QLinkedList>). Для удобства, контейнеры объявлены в <QtContainerFwd>.

Значения, хранящиеся в различных контейнерах, могут быть любого присваиваемого типа данных. Для этого тип должен предоставлять конструктор по умолчанию, конструктор копирования и оператор присваивания. Это охватывает большинство типов данных, которые вы, вероятно, захотите поместить в контейнер, включая базовые типы, такие как int и double, типы указателей и типы данных Qt, такие как QString, QDate и QTime, но не охватывает типы QObject или любые из подклассов QObject (QWidget, QDialog, QTimer, и т.д.). Если вы попытаетесь создать экземпляр QList<QWidget>, компилятор сообщит, что конструктор копирования и операторы присваивания QWidget запрещены. Если вы хотите поместить эти виды объектов в контейнер, то поместите указатели на них, например, так QList<QWidget *>

Вот пример пользовательского типа данных, который отвечает требованием присваиваемого типа данных:

 class Employee

 {

 public:

     Employee() {}

     Employee(const Employee &other);

 

     Employee &operator=(const Employee &other);

 

 private:

     QString myName;

     QDate myDateOfBirth;

 };

Если вы не предоставляете конструктор копирования и оператор присваивания, C++ предоставляет реализацию по умолчанию, которая выполняет копирование объекта почленно. Определение класса в вышеприведенном примере достаточно. Также, если вы не предоставляете никаких конструкторов, то C++ предоставляет конструктор по умолчанию, который инициализирует члены класса используя их конструкторы по умолчанию. Следующий тип данных может быть помещен в контейнер, несмотря на то, что он не предоставляет явно никаких конструкторов и оператора присваивания:

 struct Movie

 {

     int id;

     QString title;

     QDate releaseDate;

 };

Некоторые контейнеры предъявляют дополнительные требования к типам данных, которые они могут хранить. Например, тип Key контейнера QMap<Key, T> должен предоставить operator<(). Такие особые требования документированы в подробном описании классов. В некоторых случаях, определенные функции предъявляют специальные требования; они указаны в описаниях функций. Если эти требования не выполняются, компилятор всегда будет генерировать ошибку

Контейнеры Qt предоставляют operator<<() и operator>>(), и, поэтому, они могут быть легко прочитаны и записаны используя QDataStream. Это означает, что типы данных, помещаемых в контейнер, также должны поддерживать operator<<() и operator>>(). Предоставление такой поддержки просто; вот как мы могли бы сделать ее для структуры Movie приведенной выше:

 QDataStream &operator<<(QDataStream &out, const Movie &movie)

 {

     out << (quint32)movie.id << movie.title

         << movie.releaseDate;

     return out;

 }

 

 QDataStream &operator>>(QDataStream &in, Movie &movie)

 {

     quint32 id;

     QDate date;

 

     in >> id >> movie.title >> date;

     movie.id = (int)id;

     movie.releaseDate = date;

     return in;

 }

Документация некоторых функций классов-контейнеров ссылается на значения конструируемые по умолчанию; например, QVector автоматически инициализирует свои элементы значениями по умолчанию, а QMap::value() возвращает значение по умолчанию, если указанный ключ отсутствует в словаре. Для большинства типов значений это просто означает, что они созданы используя конструктор по умолчанию (например, пустая строка для QString). Но для примитивных типов, подобных int и double, как и для типов указателей, язык C++ не предусматривает никакой инициализации; в этих случаях, контейнеры Qt автоматически инициализируют значения нулем.

Если Вам понравилась статья, проголосуйте за нее

Голосов: 6  loading...
toxx   MayRiv   something   ingwarsmith   partigiano   smay1612