Неявное совместное использование
Многие классы 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. См. Проблему итераторов при неявном совместном использовании.
Массив битов |
|
Монохромные (глубина 1 бит) растровые изображения |
|
Определяет узор заливки фигур, отрисовываемых QPainter |
|
Массив байтов |
|
Список массивов байтов |
|
Шаблонный класс, предоставляющий кэш |
|
Сравнивает строки в соответствии с алгоритмом сортировки, локализованным для определенного языка |
|
Может использоваться для ускорения сортировки строк |
|
Определяет возможный параметр командной строки |
|
Шаблонный класс, предоставляющий непрерывный кэш |
|
Курсор мыши с произвольной формой |
|
Ссылается на одну ожидающую асинхронную операцию |
|
Содержит один дескриптор Unix-файла |
|
Функции даты и времени |
|
Поток вывода для отладочной информации |
|
Доступ к структурам каталогов и их содержимому |
|
Хранит информацию о записи доменного имени |
|
Хранит информацию о записи адреса хоста |
|
Хранит информацию о записи DNS MX |
|
Хранит информацию о записи DNS SRV |
|
Хранит информацию о записи DNS TXT |
|
Независимая от платформы информация о файлах |
|
Определяет шрифт, используемый для отрисовки текста |
|
Общая информация о шрифтах |
|
Информация о метрике шрифта |
|
Информация о метрике шрифта |
|
Прямой доступ к внутренним глифам в шрифте |
|
Используется в сочетании с QBrush для задания градиентной заливки |
|
Шаблонный класс, предоставляющий словарь на основе хеш-таблицы |
|
IP-адрес |
|
Содержит часть тела для использования внутри сообщения 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 |
|
Интерфейс для параметров Diffie-Hellman для серверов |
|
Ошибка 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/archives/qt-5.11/implicit-sharing.html