У меня здесь пять классов, класс A B C, я могу объяснить их размер.
класс D Я ожидаю, что результат будет 12 байт, но вывод будет 16 байт, я обнаружил, что причина в том, что после добавления виртуальной функции выравнивание станет 8 байт,
Итак, я снова создал класс Test, согласно приведенным выше рассуждениям, мой ожидаемый результат — 16 байт, но после запуска результат — 12 байт,
Не должен ли класс Test также быть выравниванием 8 байт, а результат должен быть 16 байт? Или что заставляет класс выполнять выравнивание 8 байт?
Код:
#include <iostream>
using namespace std;
class A
{
//empty
};
class B
{
int a = 123;
};
class C
{
public:
void print(){
cout << "C" << endl;
}
private:
int i = 123;
};
class D
{
public:
virtual void print(){
std::cout << "D" << std::endl;
}
virtual int d(){
return 0;
}
void add(){
std::cout << "D add" << std::endl;
}
private:
int i;
};
class Test
{
private:
int i;
int j;
int l;
};
int main(){
cout << sizeof(A) << endl;//1 byte:avoid null pointer
cout << sizeof(B) << endl;//4 bytes:one int
cout << sizeof(C) << endl;//4 bytes:one int
cout << sizeof(D) << endl;//16 bytes(using 12byte):one int + one pointer and 8 alignment
cout << sizeof(Test) << endl;//12 bytes:Why not 16 bytes?
return 0;
}
а для D это один int + 8-байтовый указатель + 4 байта заполнения (не 8)
@ixSci Я думаю, что OP считает, что у D есть отступы, поэтому у Test тоже должны быть отступы.
Выравнивание каждого int (при условии, что int 32-битное, что обеспечивает ваш компилятор) — это четырехбайтовая граница, поэтому единственное требование для выравнивания Test состоит в том, чтобы каждый int находился на четырехбайтовой границе. Нет требований к 16-битному выравниванию Test в целом. В отличие от D, Test не имеет виртуальных функций, поэтому (для компиляторов, которые включают указатель на виртуальную таблицу в каждый экземпляр класса с виртуальными функциями, что, по-видимому, делает ваш компилятор) D будет иметь виртуальную таблицу, а Test не будет.
Я думал, что наибольшее выравнивание следует использовать в любом случае, но на самом деле оно должно быть таким же, как и самый большой тип данных, верно?
Компилятор должен выбрать такое выравнивание, чтобы при создании массива структур все члены всех элементов были правильно выровнены. Это имеет мало общего с размером членов, больше с их требуемым выравниванием.
Например, при добавлении виртуальной функции к структуре добавляется указатель (обычно в начале, чтобы его было легко найти). Это делает всю структуру выровненной как выравнивание этого указателя.
Размер пустого класса не равен 1, чтобы «избежать нулевого указателя», он равен 1, чтобы дать каждому объекту свое уникальное местоположение. (Если у вас есть массив A as[3], у вас не может быть &as[0] + 1 == &as[0] + 2.)
Хорошо, я думаю, я понял. Спасибо





class D I expect the result is 12 bytes, but the output is 16 bytes
Ваше ожидание ошибочно.
I found the reason is that after adding the virtual function, the alignment will become 8 bytes,
Вот в чем причина. 12 не выровнено по 8 байтам. 16 есть.
So I created the Test class again, according to the above reasoning, my expected result is 16 bytes, but after running, the result is 12 bytes,
Вы не добавили виртуальные функции в Test, поэтому ваши ожидания неверны.
Should not the Test class is also 8 bytes alignment,
Нет причин ожидать этого.
Or what causes the class to perform 8 bytes alignment?
В данном случае это было вызвано наличием виртуальной функции-члена. В других случаях это также может быть вызвано наличием подобъекта с выравниванием 8.
Testимеет 3 члена одного и того же мировоззрения, которое на вашей платформе кажется 4 байта. Как вы думаете, почему должно быть 8?