Неявное совместное использование
Многие классы C++ в Qt используют неявное совместное использование данных для максимального использования ресурсов и минимизации копирования. Неявные общие классы безопасны и эффективны при передаче в качестве аргументов, поскольку передаётся только указатель на данные, а данные копируются только в том случае, если функция записывает в них, т.е. копирование при записи.
Обзор
Класс, использующий совместное использование, состоит из указателя на блок общих данных, который содержит счётчик ссылок и сами данные.
При создании объекта, использующего совместное использование, счётчик ссылок устанавливается в 1. Счётчик ссылок увеличивается всякий раз, когда новый объект ссылается на общие данные, и уменьшается, когда объект прекращает ссылаться на общие данные. Общие данные удаляются, когда счётчик ссылок становится равным нулю.
При работе с объектами, использующими совместное использование, существуют два способа копирования объекта. Обычно мы говорим о полных и неполных копиях. Полная копия подразумевает дублирование объекта. Неполная копия — это ссылка на копию, т.е. просто указатель на блок общих данных. Создание полной копии может быть дорогостоящим с точки зрения памяти и процессора. Создание неполной копии очень быстро, потому что это включает только установку указателя и увеличение счётчика ссылок.
Присваивание объекта (с оператором =()) для объектов с неявным совместным использованием реализуется с помощью неполных копий.
Преимущества совместного использования заключаются в том, что программе не нужно излишне дублировать данные, что приводит к меньшему использованию памяти и меньшему копированию данных. Объекты легко можно присваивать, передавать в качестве аргументов функций и возвращать из функций.
Неявное совместное использование в основном происходит за кулисами; программисту редко нужно о нём беспокоиться. Однако итераторы контейнеров Qt ведут себя иначе, чем итераторы из STL. Прочитайте Проблема итераторов при неявном совместном использовании.
В многопоточных приложениях неявное совместное использование происходит, как объяснено в Потоки и классы с неявным совместным использованием.
При реализации собственных классов с неявным совместным использованием используйте классы QSharedData и QSharedDataPointer.
Подробное описание неявного совместного использования
Неявное совместное использование автоматически отсоединяет объект от общего блока, если объект собирается измениться, и счётчик ссылок больше единицы. (Это часто называется копированием при записи или семантикой значений.)
Класс с неявным совместным использованием управляет своими внутренними данными. В любых методах, которые изменяют его данные, он автоматически отсоединяется перед изменением данных. Обратите внимание, однако, на особый случай с итераторами контейнеров; см. Проблема итераторов при неявном совместном использовании.
Класс QPen, использующий неявное совместное использование, отсоединяется от общих данных во всех методах, изменяющих внутренние данные.
Фрагмент кода:
void QPen::setStyle(Qt::PenStyle style)
{
detach(); // detach from common data
d->style = style; // set the style member
}
void QPen::detach()
{
if (d->ref != 1) {
... // perform a deep copy
}
} Список классов
Перечисленные ниже классы автоматически отсоединяются от общих данных, если объект собирается измениться. Программист даже не заметит, что объекты объединены. Таким образом, вы должны рассматривать отдельные экземпляры как отдельные объекты. Они всегда будут вести себя как отдельные объекты, но с дополнительным преимуществом совместного использования данных, когда это возможно. По этой причине вы можете передавать экземпляры этих классов в функции по значению, не беспокоясь о расходах на копирование.
Пример:
QPixmap p1, p2;
p1.load("image.bmp");
p2 = p1; // p1 and p2 share data
QPainter paint;
paint.begin(&p2); // cuts p2 loose from p1
paint.drawText(0,50, "Hi");
paint.end(); В этом примере, p1 и p2 совместно используют данные до тех пор, пока QPainter::begin() не будет вызван для p2, поскольку отрисовка пиксельного изображения изменит его.
Предупреждение: Будьте осторожны при копировании контейнера с неявным совместным использованием (QMap, QVector и т.д.) при использовании итераторов STL-стиля. См. Проблема итераторов при неявном совместном использовании.
Поток вывода для отладки |
|
Доступ к структурам каталогов и их содержимому |
|
Независимая от системы информация о файлах |
|
Содержит переменные среды, которые могут быть переданы программе |
|
Предоставляет информацию о подключенных хранилищах и дисках |
|
Удобный интерфейс для работы с URL-адресами |
|
Способ манипулирования парами «ключ-значение» в запросе URL |
|
Используется для поиска данных в модели данных |
|
Оборачивает массив JSON |
|
Способ чтения и записи документов JSON |
|
Используется для сообщения об ошибках во время разбора JSON |
|
Оборачивает объект JSON |
|
Оборачивает значение в JSON |
|
Выступает как объединение для наиболее распространенных типов данных Qt |
|
Описывает типы файлов или данных, представленные строкой MIME-типа |
|
Массив битов |
|
Массив байтов |
|
Список массивов байтов |
|
Шаблонный класс, который предоставляет кэш |
|
Сравнивает строки в соответствии с алгоритмом сортировки с учетом локали |
|
Может быть использован для ускорения сортировки строк с учетом локали |
|
Определяет возможный параметр командной строки |
|
Шаблонный класс, который предоставляет непрерывный кэш |
|
Функции даты и времени |
|
Шаблонный класс, предоставляющий словарь на основе хеш-таблицы |
|
Вспомогательный подкласс QHash, предоставляющий хеши с множественными значениями |
|
Шаблонный класс, предоставляющий связанные списки |
|
Шаблонный класс, предоставляющий списки |
|
Преобразует числа в строковые представления и обратно на разных языках |
|
Шаблонный класс, предоставляющий словарь на основе красно-черного дерева |
|
Вспомогательный подкласс QMap, предоставляющий карты с множественными значениями |
|
Обобщенный контейнер, предоставляющий очередь |
|
Сопоставление шаблонов с помощью регулярных выражений |
|
Сопоставление шаблонов с помощью регулярных выражений |
|
Результаты сопоставления QRegularExpression со строкой |
|
Итератор по результатам глобального сопоставления объекта QRegularExpression со строкой |
|
Шаблонный класс, предоставляющий множество на основе хеш-таблицы |
|
Шаблонный класс, предоставляющий стек |
|
Строка Unicode |
|
Список строк |
|
Способ поиска границ текста Unicode в строке |
|
Шаблонный класс, предоставляющий динамический массив |
|
Ссылается на один ожидающий асинхронный вызов |
|
Содержит один дескриптор Unix-файла |
|
Монохромные (глубина 1 бит) пиксельмапы |
|
Масштабируемые значки в различных режимах и состояниях |
|
Независимая от оборудования структура изображения, позволяющая получить прямой доступ к данным пикселей, и может использоваться в качестве устройства рисования |
|
Устройство рисования, которое записывает и воспроизводит команды QPainter |
|
Представление изображения вне экрана, которое может использоваться в качестве устройства рисования |
|
Курсор мыши с произвольной формой |
|
Оборачивает последовательность нажатий клавиш, используемую для ярлыков |
|
Содержит группы цветов для каждого состояния виджета |
|
Оборачивает сообщение об отладке OpenGL |
|
Определяет узор заливки фигур, нарисованных с помощью QPainter |
|
Используется в сочетании с QBrush для задания градиентной заливки |
|
Контейнер для операций рисования, позволяющий создавать и повторно использовать графические фигуры |
|
Определяет, как QPainter должен рисовать линии и контуры фигур |
|
Вектор точек с целочисленной точностью |
|
Вектор точек с плавающей точкой |
|
Определяет область обрезки для художника |
|
Определяет шрифт, используемый для рисования текста |
|
Общая информация о шрифтах |
|
Информация о метриках шрифта |
|
Информация о метриках шрифта |
|
Прямой доступ к внутренним глифам в шрифте |
|
Доступ к одному физическому экземпляру шрифта |
Обеспечивает оптимизированное отображение текста, когда текст и его макет обновляются редко |
|
Предлагает API для доступа к и изменения QTextDocuments |
|
Представляет собой фрагмент форматированного текста из QTextDocument |
|
Информация о форматировании блоков текста в QTextDocument |
|
Информация о форматировании символов в QTextDocument |
|
Информация о форматировании QTextDocument |
|
Информация о форматировании фреймов в QTextDocument |
|
Информация о форматировании изображений в QTextDocument |
|
Информация о форматировании списков в QTextDocument |
|
Информация о форматировании ячеек таблиц в QTextDocument |
|
Информация о форматировании таблиц в QTextDocument |
|
Информация о кэше |
|
Содержит часть тела, которая используется внутри HTTP-сообщения MIME с несколькими частями |
|
Содержит один сетевой cookie |
|
Содержит запрос, который должен быть отправлен с QNetworkAccessManager |
|
Абстракция одной или нескольких конфигураций точек доступа |
|
Хранит информацию о записи доменного имени |
|
Хранит информацию о записи адреса хоста |
|
Хранит информацию о записи MX DNS |
|
Хранит информацию о записи SRV DNS |
|
Хранит информацию о записи TXT DNS |
|
Хранит один IP-адрес, поддерживаемый сетевым интерфейсом, вместе с его маской сети и широковещательным адресом |
|
Список IP-адресов и сетевых интерфейсов хоста |
|
Прокси сетевого уровня |
|
Используется для запроса настроек прокси для сокета |
|
Удобный API для сертификата X509 |
|
API для доступа к расширениям сертификата X509 |
|
Представляет собой криптографический шифр SSL |
|
Хранит конфигурацию и состояние соединения SSL |
|
Ошибка SSL |
|
Интерфейс для закрытых и открытых ключей |
|
Данные аутентификации для шифров с предварительно объявленными ключами (PSK) |
|
Работает с полями в таблицах и представлениях баз данных SQL |
|
Средство выполнения и обработки SQL-запросов |
|
Инкапсулирует запись базы данных |
© The Qt Company Ltd
Licensed under the GNU Free Documentation License, Version 1.3.
https://doc.qt.io/archives/qt-5.6/implicit-sharing.html