Неявное совместное использование
Многие классы 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/qt-5.12/implicit-sharing.html