Trivial class

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

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

  • виртуальных функций

  • нетривиальных базовых классов

  • нетривиальных типов данных

Под словом "тривиальный" понимается наличие:

  • тривиальных специальных функций-членов (msdn)

  • POD членов (см. ниже)

Тривиальные классы могут быть безопасно скопированы функциями типа memcpy в полной точности.

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

  • выделение памяти под объект без инициализации

  • побайтовое копирование объекта

  • освобождение памяти без очистки

// тривиальный, есть явный конструктор по умолчанию
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) - как написано так и храниться в памяти.

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

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

  • отсутствие управляющего кода (тривиальный класс)

  • предсказуемое устройство памяти (стандартная структура)

struct POD
{
  int a;
  int b;
};

Автор: Виталий Бутурлин

Источник