Trivial class
Тривиальные классы (trivial class) - это классы или структуры, в которых специальные функции-члены предоставляются компилятором (явно отсутствует реализация) либо явно заданы как default. В таком классе нет управляющего кода, так как специальные функции-члены обьявлены (явно или неявно) тривиальными по умолчанию.
Кроме того есть дополнительные требования, тривиальный класс не должен иметь:
- виртуальных функций
- нетривиальных базовых классов
- нетривиальных типов данных
- тривиальных специальных функций-членов (msdn)
- POD членов (см. ниже)
Тривиальность функций членов (отсутсвие управляющего кода) подразумевает:
- выделение памяти под обьект без инициализации
- побайтовое копирование обьекта
- освобождение памяти без очистки
// тривиальный, есть явный конструктор по умолчанию 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)
- нестатические члены ссылочного типа
- не имеет члены являющиеся нестандартной структурой
- не имеет базовые классы не являющиеся нестандартной структурой
- не имеет более одного базового класса с нестатическими членами данных
- не имеет двух мест обьявления нестатических членов (например в базовом классе и у себя)
- не имеет более двух базовых (или косвенно) классов
// 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 обладает сразу двумя свойствами:
- отсутсвие управляющего кода (тривиальный класс)
- предсказуемое устройство памяти (стандартная структура)
struct POD { int a; int b; };
Дополнительно:
- https://docs.microsoft.com/ru-ru/cpp/cpp/trivial-standard-layout-and-pod-types?view=vs-2019
- https://en.cppreference.com/w/cpp/named_req/StandardLayoutType
- https://en.cppreference.com/w/cpp/language/data_members#Standard_layout
- https://en.cppreference.com/w/cpp/language/aggregate_initialization
- https://en.cppreference.com/w/cpp/named_req/PODType
- https://en.cppreference.com/w/cpp/language/default_constructor
- https://ru.wikipedia.org/wiki/Простая_структура_данных