Стандартная компоновка C++

Я просматривал отличные статьи о классах C++ POD, Trivial и Standard Layout. Одно свойство, которое я не совсем понял в отношении стандартного макета, заключается в следующем:

 A standard layout has no base classes of the same type as the first 
    non-static data member

Таким образом, следующее не будет стандартным макетом, так как в нем первый член совпадает с базовым классом.

struct NonStandardLayout3 : StandardLayout1 {
    StandardLayout1 x; // first member cannot be of the same type as base
};

Но с точки зрения производительности и свойств как вышеприведенная структура отличается от

struct StandardLayout5 : StandardLayout1 {
    int x;
    StandardLayout1 y; // can have members of base type if they're not the first   
};

что является исправлением вышеупомянутого.

1 ответ

Решение

Причина заключается в том, что стандартные типы макетов эффективно предписывают "пустую оптимизацию базового класса", когда базовые классы без элементов данных не занимают места и имеют тот же адрес, что и первый элемент данных (если есть) производного класса.

Однако попытка сделать это, когда базовый класс имеет тот же тип, что и первый член данных, нарушает модель памяти C++, которая требует, чтобы разные объекты одного типа имели разные адреса.

Из ИСО / МЭК 14882:2011 1.8 [intro.object]/6:

Два объекта, которые не являются битовыми полями, могут иметь один и тот же адрес, если один является подобъектом другого, или если хотя бы один является подобъектом базового класса нулевого размера, и они имеют разные типы; в противном случае они должны иметь разные адреса

эффективно назначая пустой базовый класс, 9.2 [class.mem] /20:

Указатель на объект структуры стандартной компоновки, соответствующим образом преобразованный с использованием reinterpret_cast, указывает на свой начальный элемент (или, если этот элемент является битовым полем, то на модуль, в котором он находится), и наоборот.

Это было бы невозможно для следующих типов (Type1 а также Type2) быть совместимым с макетом (хотя в противном случае он будет стандартным классом макета) без этого ограничения.

struct S1 {};
struct S2 {};

struct Type1 : S1 {
    S1 s;
    int k;
};

struct Type2 : S1 {
    S2 s;
    int m;
};
Другие вопросы по тегам