Подтвердить что ты не робот

Почему размер класса зависит от порядка объявления участника? и как?

Кто-нибудь объяснит мне, как порядок объявления участника внутри класса определяет размер этого класса.

Пример:

class temp
{
public:
    int i;
    short s;
    char c;
};

Размер вышеприведенного класса - 8 байтов.

Но когда порядок объявления участника изменяется ниже

class temp
{
public:
    char c;
    int i;
    short s;
};

тогда размер класса составляет 12 байтов.

Как?

4b9b3361

Ответ 1

Причина вышеописанного поведения - выравнивание структуры данных и добавление. В принципе, если вы создаете 4 байтовую переменную, например. int, он будет выровнен с границей в четыре байта, то есть он начнется с адреса в памяти, который будет кратен 4. То же самое относится к другим типам данных. 2 байта должны начинаться с четного адреса памяти и т.д.

Следовательно, если у вас есть 1 байтовый символ, объявленный перед int (предположим, 4 байта здесь), между ними останется 3 свободных байта. Общий термин, используемый для них, - "padded"

Выравнивание структуры данных

Еще одно хорошее иллюстрированное объяснение

Причина выравнивания

Заполнение позволяет более быстрый доступ к памяти, то есть для процессора, доступ к областям памяти, которые выровнены быстрее, например. чтение 4-байтового выровненного целого числа может принимать однонаправленный вызов, где, как если бы целое число находилось в некорректированном диапазоне адресов (например, адрес 0x0002 - 0x0006), тогда потребовалось бы двух считываний памяти, чтобы получить это целое число.

Один из способов заставить компилятор избегать выравнивания (зависит от gcc/g++), чтобы использовать ключевое слово "упакованное" с атрибутом структуры. упакованное ключевое слово Также ссылка указывает, как обеспечить выравнивание по определенной границе вашего выбора (2, 4, 8 и т.д.), используя выровненное ключевое слово.

Лучшая практика

Всегда полезно структурировать свой класс/структуру таким образом, чтобы переменные уже были выровнены с минимальным заполнением. Это уменьшает размер класса в целом плюс уменьшает объем работы, выполняемой компилятором, т.е. Никакой перегруппировки структуры. Также всегда нужно обращаться к переменным-членам по их именам в коде, а не пытаться прочитать конкретный байт из структуры, предполагая, что значение будет находиться в этом байте.

Еще один полезный SO вопрос о преимуществах производительности выравнивания

Для завершения следующего размера по-прежнему будет иметь размер 8 байт в вашем сценарии (32-разрядная машина), но он не улучшится, так как теперь заняты все 8 байтов, и нет прокладки.

class temp
{
public:
    int i;
    short s;
    char c;
    char c2;
};

Ответ 2

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

temp [ i [0-4]; s [4-2]; c [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

temp [ c [0-1]; i [4-8]; s [8-10]]] → 12 Заполнение в (1-4) и (10-12)