Неявное совместное использование
Многие классы C++ в Qt используют неявное совместное использование данных, чтобы максимизировать использование ресурсов и минимизировать копирование. Неявные общие классы безопасны и эффективны при передаче в качестве аргументов, потому что передается только указатель на данные, а данные копируются только тогда, когда функция записывает в них, то есть copy-on-write.
Обзор
Общий класс состоит из указателя на общий блок данных, который содержит счетчик ссылок и данные.
При создании общего объекта счетчик ссылок устанавливается в 1. Счетчик ссылок увеличивается всякий раз, когда новый объект ссылается на общие данные, и уменьшается, когда объект прекращает ссылаться на общие данные. Общие данные удаляются, когда счетчик ссылок становится равным нулю.
При работе с общими объектами существует два способа копирования объекта. Обычно мы говорим о глубокой и поверхностной копиях. Глубокая копия подразумевает дублирование объекта. Поверхностная копия — это ссылка на копию, то есть просто указатель на общий блок данных. Создание глубокой копии может быть дорогостоящим с точки зрения памяти и ЦП. Создание поверхностной копии очень быстро, потому что оно включает только установку указателя и увеличение счетчика ссылок.
Присваивание объекта (с помощью оператора =()) для неявно общих объектов реализуется с помощью поверхностных копий.
Преимущество совместного использования заключается в том, что программе не нужно излишне дублировать данные, что приводит к снижению использования памяти и сокращению копирования данных. Объекты легко можно присваивать, передавать в качестве аргументов функций и возвращать из функций.
Неявное совместное использование в основном происходит за кулисами; программисту редко приходится беспокоиться об этом. Однако итераторы контейнеров Qt имеют другое поведение, чем итераторы STL. Прочитайте Проблемы итераторов при неявном совместном использовании.
В многопоточных приложениях неявное совместное использование происходит, как описано в Потоки и неявно общие классы.
При реализации собственных неявно общих классов используйте классы QSharedData и QSharedDataPointer.
Подробное описание неявного совместного использования
Неявное совместное использование автоматически отсоединяет объект от общего блока, если объект собирается изменить, и счетчик ссылок больше единицы. (Это часто называется copy-on-write или смысл значений.)
Неявно общий класс управляет своими внутренними данными. Во всех методах-членах, которые изменяют его данные, он автоматически отсоединяется перед изменением данных. Обратите внимание, однако, на особый случай с итераторами контейнеров; см. Проблемы итераторов при неявном совместном использовании.
Класс 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. См. Проблемы итераторов при неявном совместном использовании.
Массив битов |
|
Монохромные (глубина 1 бит) пиксельные карты |
|
Определяет узор заливки фигур, отрисовываемых QPainter |
|
Массив байтов |
|
Список массивов байтов |
|
Шаблонный класс, предоставляющий кэш |
|
Сравнивает строки в соответствии с локальным алгоритмом сортировки |
|
Может использоваться для ускорения сортировки строк |
|
Определяет возможный параметр командной строки |
|
Шаблонный класс, предоставляющий непрерывный кэш |
|
Курсор мыши с произвольной формой |
|
Ссылается на один ожидающий асинхронный вызов |
|
Содержит один дескриптор Unix-файла |
|
Функции работы с датой и временем |
|
Поток вывода для отладочной информации |
|
Доступ к структурам каталогов и их содержимому |
|
Хранит информацию о записи доменного имени |
|
Хранит информацию о записи адреса хоста |
|
Хранит информацию о записи DNS MX |
|
Хранит информацию о записи DNS SRV |
|
Хранит информацию о записи DNS TXT |
|
Независимая от системы информация о файлах |
|
Указывает запрос на шрифт, используемый для отрисовки текста |
|
Общая информация о шрифтах |
|
Информация о метриках шрифта |
|
Информация о метриках шрифта |
|
Прямой доступ к внутренним глифам в шрифте |
|
Используется совместно с QBrush для указания градиентной заливки |
|
Шаблонный класс, предоставляющий словарь на основе хеш-таблицы |
|
IP-адрес |
|
Управляет параметрами и настройками HTTP/2 |
|
Содержит часть тела, используемую внутри сообщения HTTP multipart MIME |
|
Масштабируемые значки в различных режимах и состояниях |
|
Независимое от аппаратного обеспечения представление изображения, позволяющее получать прямой доступ к данным пикселей и может использоваться как устройство отрисовки |
|
Запечатывает массив JSON |
|
Способ чтения и записи документов JSON |
|
Запечатывает объект JSON |
|
Используется для сообщения об ошибках во время разбора JSON |
|
Запечатывает значение в JSON |
|
Запечатывает последовательность клавиш, как используется в ярлыках |
|
Шаблонный класс, предоставляющий связанные списки |
|
Шаблонный класс, предоставляющий списки |
|
Преобразование между числами и их строковыми представлениями на различных языках |
|
Шаблонный класс, предоставляющий словарь на основе красно-черного дерева |
|
Описание типов файлов или данных, представленных строкой MIME-типа |
|
Подкласс QHash, предоставляющий многозначные хеш-таблицы |
|
Подкласс QMap, предоставляющий многозначные отображения |
|
Хранит один IP-адрес, поддерживаемый сетевым интерфейсом, вместе с его маской сети и широковещательным адресом |
|
Информация о кэше |
|
Абстракция одной или нескольких конфигураций точек доступа |
|
Содержит один сетевой cookie |
|
Список IP-адресов и сетевых интерфейсов хоста |
|
Прокси-сервер сетевого уровня |
|
Используется для запроса настроек прокси-сервера для сокета |
|
Содержит запрос, который будет отправлен с помощью QNetworkAccessManager |
|
Оборачивает сообщение об отладке OpenGL |
|
Контейнер для операций рисования, позволяющий создавать и повторно использовать графические фигуры |
|
Содержит группы цветов для каждого состояния виджета |
|
Определяет, как QPainter должен рисовать линии и контуры фигур |
|
Используется для поиска данных в модели данных |
|
Устройство отрисовки, которое записывает и воспроизводит команды QPainter |
|
Представление изображения вне экрана, которое может использоваться как устройство отрисовки |
|
Вектор точек с использованием целочисленной точности |
|
Вектор точек с использованием плавающей точки точности |
|
Хранит переменные среды, которые могут быть переданы программе |
Обобщённый контейнер, предоставляющий очередь |
|
Доступ к одному физическому экземпляру шрифта |
|
Сопоставление с образцом с использованием регулярных выражений |
|
Определяет область обрезки для художника |
|
Сопоставление с образцом с использованием регулярных выражений |
|
Результаты сопоставления QRegularExpression со строкой |
|
Итератор по результатам глобального сопоставления объекта QRegularExpression со строкой |
|
Шаблонный класс, предоставляющий множество на основе хеш-таблицы |
|
Удобный API для сертификата X509 |
|
API для доступа к расширениям сертификата X509 |
|
Представляет криптографическое шифрование SSL |
|
Содержит конфигурацию и состояние соединения SSL |
|
Интерфейс для параметров Диффи-Хеллмана для серверов |
|
Ошибка SSL |
|
Интерфейс для закрытых и открытых ключей |
|
Данные аутентификации для шифров предварительно общих ключей (PSK) |
|
Шаблонный класс, предоставляющий стек |
|
Обеспечивает оптимизированный вывод текста, когда текст и его макет редко обновляются |
|
Предоставляет информацию о подключённых хранилищах и дисках |
|
Строка с символами Юникод |
|
Список строк |
|
Информация о форматировании блоков текста в QTextDocument |
|
Способ нахождения границ текста Юникод в строке |
|
Информация о форматировании символов в QTextDocument |
|
Предлагает API для доступа и изменения QTextDocuments |
|
Представляет фрагмент форматированного текста из QTextDocument |
|
Информация о форматировании для QTextDocument |
|
Информация о форматировании фреймов в QTextDocument |
|
Информация о форматировании изображений в QTextDocument |
|
Информация о форматировании списков в QTextDocument |
|
Информация о форматировании ячеек таблицы в QTextDocument |
|
Информация о форматировании таблиц в QTextDocument |
|
Удобный интерфейс для работы с URL-адресами |
|
Способ манипулирования парами ключ-значение в запросе URL |
|
Выступает как объединение для наиболее распространённых типов данных Qt |
|
Шаблонный класс, предоставляющий динамический массив |
© The Qt Company Ltd
Licensed under the GNU Free Documentation License, Version 1.3.
https://doc.qt.io/qt-5.14/implicit-sharing.html