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