Классы-контейнеры TulipQt 4 представляет новый набор контейнеров, заменяющих старый контейнер указателей QCollection и более новый, основанный на значениях QTL. Общий обзорКонтейнеры Tulip заменяют собой QTL контейнеры Qt 3 (QValueList, QValueVector, QMap), но имеют ряд преимуществ:
Tulip предоставляет следующий набор контейнеров: QList, QLinkedList, QVector, QStack и QQueue. В большинстве приложений лучше всего использовать QList. Класс реализован в виде списка-массива, что позволяет быстро добавлять в начало и в конец. Если вам нужен настоящий связанный список, то используйте QLinkedList; если вы хотите размещать записи в памяти рядом, обратите внимание на QVector. QStack и QQueue - вспомогательные классы, предоставляющие семантику FIFO и LIFO. Tulip также предоставляет следующие ассоциативные контейнеры: QMap, QMultiMap, QHash, QMultiHash и QSet. "Multi" контейнеры поддерживают ассоциирование нескольких значений с одним ключом. "Hash" контейнеры предоставляют быстрый доступ с использованием хэш-функции для бинарного поиска в отсортированном наборе. Контейнеры Tulip поддерживают конструкцию foreach - Qt-специфичную добавку к языку C++, использующую стандартный C++ препроцессор. Её синтаксис: foreach (variable, container) выражение; Пример: QList<QString> list; ... foreach (const QString &str, list) cout << str.ascii() << endl; Переменная-итератор может быть объявлена и вне цикла. Например: QString str; foreach (str, list) cout << str.ascii() << endl; Как и for, foreach поддерживает, break, continue и вложенность. Qt делает копию контейнера перед входом в цикл. Если вы измените контейнер во время выполнения цикла, то в цикле это не даст эффекта. Для получения детальной информации о новых контейнерах смотрите обзоры Контейнерные классы и Основные алгоритмы. В добавок к новым контейнерам значительно много усилий было вложено в QByteArray и QString. В Qt 3 класс QCString был подобен QByteArray. Новый QByteArray автоматически добавляет разделитель '\0' после последнего символа. Например, массив байтов размера 5 содержащий "abcde" имеет нулевой байт в позиции 5 (один байт дополнительно). Это устраняет все проблемы, возникавшие в Qt 3 при взаимных преобразованиях между QByteArray и QCString. Во избежание ошибок QByteArray::data() никогда не возвращает нулевой указатель. Кроме того, ликвидировано различие между нулевым указателем и указателем на пустую строку. К примеру QByteArray() == QByteArray("") и QString() == QString(""). ПримерыПервая группа примеров показывает, как использовать итераторы в стиле Java. Основное различие между итераторами стиля Java и стиля STL заключается в том, что итератор стиля Java указывает на точку между записями (либо перед первой записью, либо после последней), тогда как итератор стиля STL указывает на запись (либо на "место после последней записи"). Основное преимущество итераторов в стиле Java является то, что перебор записей вперед и назад - действия симметричные. Перебор записей в контейнере с помощью итераторов стиля Java: // forward // назад QList<QString> list; QList<QString> list; ... ... QListIterator<QString> i(list); QListIterator<QString> i(list); while (i.hasNext()) i.toBack(); cout << i.next().ascii() << endl; while (i.hasPrev()) cout << i.prev().ascii() << endl; Изменение записей с помощью итераторов стиля Java: // forward // назад QMutableListIterator<int> i(list); QMutableListIterator<int> i(list); while (i.hasNext()) i.toBack(); if (i.next() > 128) while (i.hasPrev()) i.setValue(128); if (i.prev() > 128) i.setValue(128); Удаление записей с помощью итераторов стиля Java: // forward // назад QMutableListIterator<int> i(list); QMutableListIterator<int> i(list); while (i.hasNext()) i.toBack(); if (i.next() % 2 != 0) while (i.hasPrev()) i.remove(); if (i.prev() % 2 != 0) i.remove(); Перебор записей с использованием итераторов в стиле STL и в стиле Java: // STL-style // стиль Java QMap<int, QWidget *>::const_iterator i; QMapIterator<int, QWidget *> i(map); for (i = map.begin(); i != map.end(); ++i) while (i.findNext(widget)) if (i.value() == widget) cout << "Found widget " << widget cout << "Found widget " << widget << " under key " << " under key " << i.key() << endl; << i.key() << endl; Изменение и удаление записей с использованием итераторов в стиле STL и в стиле Java: // STL-style // стиль Java QList<int>::iterator i = list.begin(); QMutableListIterator<int> i(list); while (i != list.end()) { while (i.hasNext()) { if (*i == 0) { int val = i.next(); i = list.erase(i); if (val < 0) } else { i.setValue(-val); if (*i < 0) else if (val == 0) *i = -*i; i.remove(); ++i; } } } Следующая группа примеров демонстрирует API для непосредственной работы с классами-контейнерами. API для работы с классами-контейнерами похож на классы QTL в Qt 3, но лучше во многих отношениях. Перебор записей в QList с использованием индекса (подобный способ доступа является достаточно быстрым, даже для больших списков, т.к. QList реализован в виде списка-массива): QList<double> list; ... for (int i = 0; i < list.size(); ++i) { if (list[i] < 0.0) list[i] = 0.0; } Возвращение из словаря использует значение по умолчанию, если элемент с данным ключом отсутствует: QMap<QString, int> map; ... map.value("TIMEOUT", 30); // возвращает 30, если "TIMEOUT" не определён в словаре Получение всех значений, ассоциированных с ключом в QMultiMap или QMultiHash: QMultiMap<QString, int> map; ... QList<int> values = map.values("TIMEOUT"); Сравнение с Qt 3Контейнеры Tulip содержат значения. Если вы хотите использовать список в котором каждое значение - это QWidget *, используйте QList<QWidget *>. Новые контейнеры не поддерживают автоудаления. Мы обнаружили, что на практике, единственным случаем, где нужно автоудаление является ситуация, где в контейнере содержатся значения, а не указатели (например, QList<int>, а не QList<int *>). Если вы хотите удалить все элементы, хранящиеся в контейнере, используйте qDeleteAll(). Если вы привыкли использовать QValueList в Qt 3, то в Qt 4 можете с легкостью заменить его на QList или QLinkedList. В большинстве случаев лучшим выбором является QList: как правило, он быстрее, требует меньшего кодирования и меньше памяти. Однако итераторы при работе с QLinkedList обеспечивают большую надежность, и только QLinkedList предоставляет независимые от времени методы вставки в середину списка, что может быть важно при работе со списками, содержащими тысячи элементов. Если вы привыкли использовать QValueVector или QMap в Qt 3, то при переходе на Qt 4 подобные классы (QVector, QMap) предоставят вам схожую функциональность. |
Попытка перевода Qt документации. Если есть желание присоединиться, или если есть замечания или пожелания, то заходите на форум: Перевод Qt документации на русский язык... Люди внесшие вклад в перевод: Команда переводчиков |