В этой статье не хватает ссылок на источники информации. |
Простая структура данных (англ. plain old data, POD) — в современных языках программирования высокого уровня тип данных, имеющий жёстко определённое расположение полей в памяти, не требующий ограничения доступа и автоматического управления. Переменные такого типа можно копировать простыми процедурами копирования участков памяти наподобие memcpy
. Противоположность — управляемая структура данных.
Проще всего простую структуру данных определить от противного. Если компилятор скрытно от пользователя переставил поля местами, или при создании структуры данных скрытно вызывает конструктор, или при уничтожении структуры вызывает деструктор, или при копировании — особую процедуру копирования, то это управляемая (то есть не простая) структура.
Простые структуры данных имеют две особенности.
Компилятор может автоматически перестроить структуру данных по своему усмотрению (например, изменить порядок полей. В языке C++ это возможно только в случае, если между полями есть метка доступа public/private/protected. Последовательность полей, не разделенных такой меткой, обязана размещаться в памяти в порядке объявления полей). Подобная перестройка может серьёзно сэкономить память, но нарушает совместимость. В POD’ах такая оптимизация отключена.
Другими словами: типы, отмеченные как POD, устроены в памяти в точности так, как описал программист (возможно, с некоторым выравниванием). Поэтому только POD’ы можно использовать для связи между двумя библиотеками времени выполнения. В частности — для передачи данных из программы в программу, из плагина в плагин, для связи с кодом, написанным на другом языке программирования. Чтобы быстро записать на диск сложный заголовок файла наподобие BMP, можно сформировать его в памяти, а затем записать одной командой — но структура данных, в которой формируем заголовок, также должна быть POD’ом.
Это значит, что при появлении объекта не нужно вызывать конструктор, при копировании — операцию присваивания, а при уничтожении — деструктор. Это, в свою очередь, даёт следующие преимущества:
memcpy
.union
(в Паскале соответственно record/case
).GetLastError
[1]) плохо совместимы с автоматически управляемыми типами.В C++ POD определяется от противного. Тип данных является POD’ом, если:
operator=
, принимающего на входе тот же тип);private
и protected
;По стандарту C++ простой тип данных устроен в точности так, как описано (и полностью совместим побайтно по раскладке в памяти со структурой C). Управляемую же структуру компилятор может реорганизовать так, как он сочтёт наиболее эффективным.
Определение POD до C++ 11:
Агрегатом называется либо массив, либо же класс, не имеющий:
Агрегат можно инициализировать (как в Си) списком вида = {1, 2, 3};
Скаляром называется:
(то есть тип, который не есть класс, массив или ссылка)
PODом называется либо скаляр, либо массив других PODов, либо класс, который является агрегатом, и кроме того:
«Предсказуемое устройство в памяти» и «отсутствие управляющего кода» — сходные, но разные свойства типа. Например, структуру данных STRRET
,[2] которая в Windows служит для передачи строк из одного менеджера памяти в другой, можно «обернуть» в управляющий код, но второе свойство — предсказуемое устройство — остаётся. Поэтому концепция POD’ов в C++11 разделена на три.
Класс называется "имеющим тривиальный конструктор копирования", если верно все перечисленное ниже:
Автосгенерированный тривиальный конструктор копирования есть memmove().
Точно таким же образом определяются понятия "имеющий тривиальный конструктор умолчания/оператор присваивания/конструктор перемещения/оператор перемещения".
Класс называется "имеющим тривиальный деструктор", если верно все перечисленное ниже:
Такой класс не требует разрушения, и содержащую его память можно освобождать без очистки.
Класс называется "тривиально копируемым", если у него тривиальны все вышеперечисленные специальные функции-члены (кроме конструктора умолчания, который может быть нетривиален). Скаляры, а также массивы тривиально копируемых объектов, тоже тривиально копируемы. Такие типы могут копироваться через memcpy
.
Класс называется "тривиальным", если он тривиально копируем и у него к тому же тривиален конструктор умолчания.
Иными словами, класс является тривиальным, если у него тривиальны:
T()
;T(T&)
;T(T&&)
;
~T()
;operator=(T&)
;operator=(T&&)
.Класс является типом со стандартным устройством, если:
private
, все protected
или все public
).Поясним последнее условие: в языке не может быть двух разных объектов одного типа с одинаковым адресом, из чего следует, что размер пустого (без нестатических полей) класса не может быть 0 (как минимум 1). Однако для "части B в классе class D : B" сделано исключение, и ее размер (если она пуста) может строго равняться нулю, что приводит к отсутствию каких-либо "прокладок" между началом D и его первым полем. Но при этом, если тип первого поля тоже B, исключение применяться не может, ибо (B*)&d и &(d.field1) указывают на разные объекты одного и того же типа, и потому "прокладка" нужна. Последнее условие из списка выше означает не более чем "в классах стандартного устройства таковая прокладка запрещена".
У таких типов предсказуемое устройство в памяти (например, адрес объекта как целого совпадает с адресом его первого поля, естественно, после reinterpret_cast в один и тот же тип, например в void*), их можно передавать в другую библиотеку времени выполнения и в другие языки программирования.
Тогда POD — это массив других PODов, или скаляр, или тривиальный класс со стандартным устройством, все нестатические поля которого тоже POD’ы.
Для работы с константами, вычисляемыми при компиляции, и статической инициализации в C++11 есть более мягкое понятие — литеральный тип. А именно:
T()
, либо какой-нибудь конструктор (кроме конструктора копирования и перемещения) отмечен как constexpr
;T(T&)
тривиальный;
T(T&&)
тривиальный или запрещён;~T()
;Начиная с C++ 03, существует разница между записями T t; и T t();, а равно между new T и new T().
Версия с пустыми скобками называется "инициализация значением", а без них - "инициализация по умолчанию".
Инициализация по умолчанию: если конструктор умолчания тривиален, то не делается ничего, в объекте остается мусор. Если же конструктор умолчания нетривиален, то он исполняется.
Инициализация значением: если есть явно написанный конструктор умолчания, то он исполняется. Если же нет (т.е. если конструктор умолчания тривиален или же сгенерирован автоматически), то объект сначала зануляется, и только потом исполняется конструктор (если он нетривиален). Скалярные типы при инициализации значением зануляются.
Простыми структурами данных считаются все типы, кроме:
AnsiString
, WideString
, UnicodeString
). Впрочем, если не задевать скрытые управляющие поля, а работать только с данными, System.Copy
использовать можно — не забывая, конечно, что несколько строк могут ссылаться на одну память и прежде надо вызвать функцию UniqueString
;class
. Впрочем, TObject
, TButton
и т. д. — это указатели на объект и всегда являются простыми типами!Данная страница на сайте WikiSort.ru содержит текст со страницы сайта "Википедия".
Если Вы хотите её отредактировать, то можете сделать это на странице редактирования в Википедии.
Если сделанные Вами правки не будут кем-нибудь удалены, то через несколько дней они появятся на сайте WikiSort.ru .