Вот мой код cpp.
#include <iostream>
using namespace std;
class A {
public:
int val;
char a;
};
class B: public A {
public:
char b;
};
class C: public B {
public:
char c;
};
int main()
{
cout << sizeof(A) << endl;
cout << sizeof(B) << endl;
cout << sizeof(C) << endl;
return 0;
}
Вывод программы (в gcc):
8
12
12
Этот вывод меня сильно смущает.
Я знаю, что выравнивание может быть причиной, по которой sizeof (A) равен 8. (sizeof(int) + sizeof(char) + 3 bytes padding
)
И я также думаю, что расширение sizeof (B) (sizeof(B) == sizeof(A) + sizeof(char) + 3 bytes padding
), чтобы избежать дублирования при копировании. (это правильно?)
Но что я действительно не знаю, почему sizeof (B) равен sizeof (C).
Большое спасибо.
И GCC, и Clang следуют Itanium C ++ ABI документ, в котором указаны:
… Реализации могут свободно размещать объекты в дополнении хвоста любого класса, который не был бы POD в C ++ 98
class A
это POD, поэтому компилятор не может поместить материал в его дополнение. class B
это не POD, поэтому компилятор может повторно использовать заполнение в макете базового класса для членов производных объектов. Основная идея здесь заключалась в том, что макет класса C ++ должен отражать эквивалентный макет структуры C для типов POD, но для других классов нет ограничений. Поскольку значение «POD» менялось несколько раз, они явно используют определение из C ++ 98.
РЕДАКТИРОВАТЬ: Об обосновании. POD-типы — это очень простые классы, которые могут быть реализованы как struct
в C. Для этих типов компоновка должна быть идентична компоновке, создаваемой компилятором C. В частности, они хотят, чтобы C-инструменты, такие как memcpy
за A
, Если char b;
были в пределах дополнения A
, memcpy
уничтожит это.