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