Неявное совместное использование
Многие классы 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, QList и т.д.) при использовании итераторов в стиле STL. Смотрите Проблема итераторов с неявным совместным использованием.
Массив битов |
|
Монохромные (глубина 1 бит) растровые изображения |
|
Определяет узор заливки фигур, нарисованных с помощью QPainter |
|
Массив байтов |
|
Список массивов байтов |
|
Вид на массив байтов с чтением только подмножества API QByteArray |
|
Шаблонный класс, который предоставляет кэш |
|
Сравнивает строки в соответствии с локализованным алгоритмом сортировки |
|
Может быть использован для ускорения сортировки строк |
|
Определяет возможный параметр командной строки |
|
Шаблонный класс, который предоставляет непрерывный кэш |
|
Курсор мыши с произвольной формой |
|
Ссылается на одну ожидающую асинхронную операцию |
|
Содержит один дескриптор Unix-файла |
|
Функции работы с датой и временем |
|
Поток вывода для отладочной информации |
|
Доступ к структурам каталогов и их содержимому |
|
Хранит информацию о записи доменного имени |
|
Хранит информацию о записи адреса хоста |
|
Хранит информацию о записи DNS MX |
|
Хранит информацию о записи DNS SRV |
|
Хранит информацию о записи DNS TXT |
|
Независимая от платформы информация о файлах |
|
Указывает параметры для шрифта, используемого для рисования текста |
|
Общая информация о шрифтах |
|
Информация о метрике шрифта |
|
Информация о метрике шрифта |
|
Прямой доступ к внутренним глифам шрифта |
|
Используется в сочетании с QBrush для определения градиентной заливки |
|
Шаблонный класс, который предоставляет словарь на основе хеш-таблицы |
|
IP-адрес |
|
Управляет параметрами и настройками HTTP/2 |
|
Содержит часть тела, используемую внутри сообщения HTTP multipart MIME |
|
Масштабируемые значки в различных режимах и состояниях |
|
Независимое от аппаратного обеспечения представление изображения, позволяющее напрямую обращаться к пиксельным данным и может использоваться в качестве устройства рисования |
|
Запечатывает массив JSON |
|
Способ чтения и записи документов JSON |
|
Запечатывает объект JSON |
|
Используется для отчета об ошибках при разборе JSON |
|
Запечатывает значение в JSON |
|
Запечатывает последовательность клавиш, как в сочетаниях клавиш |
|
Шаблонный класс, который предоставляет связанные списки |
|
Шаблонный класс, который предоставляет динамический массив |
|
Преобразование между числами и их строковыми представлениями на разных языках |
|
Шаблонный класс, который предоставляет ассоциативный массив |
|
Описание типов файлов или данных, представленных строкой MIME-типа |
|
Представляет фильтр темы MQTT |
|
Представляет имя темы MQTT |
|
Подклассы QHash, предоставляющие хеши с множественными значениями |
|
Шаблонный класс, предоставляющий ассоциативный массив с несколькими эквивалентными ключами |
|
Хранит один IP-адрес, поддерживаемый сетевым интерфейсом, вместе с его маской сети и широковещательным адресом |
|
Информация о кэше |
|
Содержит один сетевой cookie |
|
Список IP-адресов и сетевых интерфейсов хоста |
|
Прокси сетевого уровня |
|
Используется для запроса настроек прокси для сокета |
|
Хранит запрос, который будет отправлен с QNetworkAccessManager |
|
Оборачивает сообщение отладки OpenGL |
|
Представляет коллекцию диапазонов страниц |
|
Контейнер для операций рисования, позволяющий создавать и повторно использовать графические фигуры |
|
Содержит группы цветов для каждого состояния виджета |
|
Определяет, как QPainter должен рисовать линии и контуры фигур |
|
Используется для поиска данных в модели данных |
|
Устройство рисования, которое записывает и воспроизводит команды QPainter |
|
Представление изображения вне экрана, которое может быть использовано в качестве устройства рисования |
Список точек с целочисленной точностью |
|
Список точек с плавающей точкой |
|
Содержит переменные окружения, которые могут быть переданы программе |
|
Обобщенный контейнер, обеспечивающий очередь |
|
Доступ к одному физическому экземпляру шрифта |
|
Сопоставление шаблонов с использованием регулярных выражений |
|
Определяет область обрезки для рисовальщика |
|
Сопоставление шаблонов с использованием регулярных выражений |
|
Результаты сопоставления QRegularExpression с строкой |
|
Итератор по результатам глобального сопоставления объекта QRegularExpression со строкой |
|
Шаблонный класс, предоставляющий множество на основе хэш-таблицы |
|
Работает с полями в таблицах и представлениях баз данных SQL |
|
Средство выполнения и обработки SQL-запросов |
|
Инкапсулирует запись базы данных |
|
Удобный 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-6.1/implicit-sharing.html