Разбор понятий: trivial type, standard layout, POD

27.04.2020

Trivial class

Тривиальные классы (trivial class) - это классы или структуры, в которых специальные функции-члены предоставляются компилятором (явно отсутствует реализация) либо явно заданы как default. В таком классе нет управляющего кода, так как специальные функции-члены обьявлены (явно или неявно) тривиальными по умолчанию.

Кроме того есть дополнительные требования, тривиальный класс не должен иметь:

  • виртуальных функций
  • нетривиальных базовых классов
  • нетривиальных типов данных
Под словом "тривиальный" понимается наличие:
  • тривиальных специальных функций-членов (msdn)
  • POD членов (см. ниже)
Тривиальные классы могут быть безопасно скопированы функциями типа memcpy в полной точности.

Тривиальность функций членов (отсутсвие управляющего кода) подразумевает:

  • выделение памяти под обьект без инициализации
  • побайтовое копирование обьекта
  • освобождение памяти без очистки
•••
cpp
// тривиальный, есть явный конструктор по умолчанию class T0 { public: T0() = default; protected: int a; }; // тривиальный, есть неявный конструктор по умолчанию (implicitly-defined) class T01 { public: void func(){} protected: int a; }; /* нетривиальный, есть инициализация члена по умолчанию std::has_trivial_default_constructor<T1>() вернет false, значит конструктор по умолчанию неявно обьявлен удаленным (implicitly defined as deleted) */ class T1 { public: T1() = default; protected: int a = 0; }; // тривиальный, есть явный конструктор по умолчанию (explicitly defaulted) class T2 { public: T2() = default; T2(int _a){ a = _a; } protected: int a; }; // нетривиальный, есть явный пользовательский конструктор (user-defined default) class T3 { public: T3(){}; protected: int a; };

Standard layout

Стандартная структура (standard layout) - это структура (struct), которая не содержит специальных возможностей C++:

  • виртуальные функции и виртуальные базовые классы
  • несколько уровней доступа (private, protected)
  • нестатические члены ссылочного типа
Стандартная структура:
  • не имеет члены являющиеся нестандартной структурой
  • не имеет базовые классы не являющиеся нестандартной структурой
  • не имеет более одного базового класса с нестатическими членами данных
  • не имеет двух мест обьявления нестатических членов (например в базовом классе и у себя)
  • не имеет более двух базовых (или косвенно) классов
Стандартная структура имеет предсказуемое устройство памяти, так как не содержит данных, которые компилятор мог бы структурировать по своему усмотрению (например в случае наличия public/private/protected) - как написано так и храниться в памяти.

•••
cpp
// standard layout struct Test1 { int a; }; // standard layout struct Test2 { void Foo(){} }; // standard layout struct Test3 { int a2; void Foo3(){} }; /* non standard layout, первый нестатичный член такой же как и базовый класс */ struct Test4 : Test1 { Test1 a2; }; /* standard layout, теперь нестатичный член a3 типа Test2 (как и базовый тип этой структуры) не является первым */ struct Test5 : Test2 { Test3 a2; Test2 a3; }; // standard layout struct Test12 : Test1, Test2 {}; /* non standard layout, третий базовый класс недопустим */ struct Test123 : Test1, Test2, Test3 {}; /*non standard layout, 2 места обьявления нестатических члена в Test1 и в Test12_1 */ struct Test12_1 : Test1, Test2 { int b; }; // standard layout struct Test12_2 : Test1, Test2 { void Foo2(){} };

POD

POD (Plain Old Data - обычные старые данные) - тип данных являющий скаляром или одновременно тривиальным классом, стандартной структурой и агрегатным типом. Совместим с C, с возможностью копирования обьекта функциями типа memcpy.

POD обладает сразу двумя свойствами:

  • отсутсвие управляющего кода (тривиальный класс)
  • предсказуемое устройство памяти (стандартная структура)
•••
cpp
struct POD { int a; int b; };

Дополнительно: