Кто-то объяснит мне, как порядок объявления членов внутри класса определяет размер этого класса.
Например :
class temp
{
public:
int i;
short s;
char c;
};
Размер вышеприведенного класса составляет 8 байт.
Но когда порядок декларации члена изменяется, как показано ниже
class temp
{
public:
char c;
int i;
short s;
};
тогда размер класса составляет 12 байтов.
Как?
Причиной вышеупомянутого поведения является выравнивание и заполнение структуры данных. В основном, если вы создаете 4-байтовую переменную, например, int, он будет выровнен по четырехбайтовая граница, т.е. она будет начинаться с адреса в памяти, кратного 4. То же относится и к другим типам данных. 2 байта должны начинаться с четного адреса памяти и так далее.
Следовательно, если у вас есть 1-байтовый символ, объявленный перед int (предположим, 4 байта здесь), между ними останется 3 свободных байта. Общий термин, используемый для них — «дополненный».
Еще одно хорошее наглядное объяснение
Причина выравнивания
Заполнение обеспечивает более быстрый доступ к памяти, то есть для процессора, доступ к областям памяти, которые выровнены, быстрее, например. чтение 4-байтового выровненного целого числа может занять один вызов для чтения где, как будто целое число находится в невыровненном диапазоне адресов (скажем, адрес 0x0002 — 0x0006), тогда потребуется два чтения памяти чтобы получить это целое число.
Один из способов заставить компилятор избегать выравнивания (специфично для gcc / g ++) — использовать ключевое слово ‘уплотненный‘с атрибутом структуры. упакованное ключевое слово Также ссылка указывает, как обеспечить выравнивание по определенной границе по вашему выбору (2, 4, 8 и т. Д.), Используя выровненный ключевое слово.
Лучшая практика
Это всегда хорошая идея структурировать ваш класс / структуру таким образом, чтобы переменные уже были выровнены с минимальным заполнением. Это уменьшает размер класса в целом, а также уменьшает объем работы, выполняемой компилятором, т. Е. Нет перестройки структуры. Также следует всегда обращаться к переменным-членам по их именам в коде, а не пытаться читать конкретный байт из структуры, предполагая, что значение будет находиться в этом байте.
Еще один полезный ТАК вопрос о производительности преимущество выравнивания
Для завершения следую до сих пор имеют размер 8 байт в вашем сценарии (32-битная машина), но лучше не станет полные 8 байтов теперь заняты, и там нет отступов.
class temp
{
public:
int i;
short s;
char c;
char c2;
};
class temp
{
public:
int i; //size 4 alignment 4
short s; //size 2 alignment 2
char c; //size 1 alignment 1
}; //Size 8 alignment max(4,2,1)=4
темп [я[0-4];s[4-2];с[6-7]]] -> 8
Заполнение в (7-8)
class temp
{
public:
char c; //size 1 alignment 1
int i; //size 4 alignment 4
short s; //size 2 alignment 2
};//Size 12 alignment max(4,2,1)=4
темп [с[0-1];я[4-8];s[8-10]]] -> 12
Отступы в (1-4) и (10-12)