Почему размер класса показывает 12 и 16 байт?

У меня здесь пять классов, класс 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;
}
Test имеет 3 члена одного и того же мировоззрения, которое на вашей платформе кажется 4 байта. Как вы думаете, почему должно быть 8?
ixSci 01.04.2022 07:21

а для D это один int + 8-байтовый указатель + 4 байта заполнения (не 8)

phuclv 01.04.2022 07:22

@ixSci Я думаю, что OP считает, что у D есть отступы, поэтому у Test тоже должны быть отступы.

Louis Go 01.04.2022 07:23

Выравнивание каждого int (при условии, что int 32-битное, что обеспечивает ваш компилятор) — это четырехбайтовая граница, поэтому единственное требование для выравнивания Test состоит в том, чтобы каждый int находился на четырехбайтовой границе. Нет требований к 16-битному выравниванию Test в целом. В отличие от D, Test не имеет виртуальных функций, поэтому (для компиляторов, которые включают указатель на виртуальную таблицу в каждый экземпляр класса с виртуальными функциями, что, по-видимому, делает ваш компилятор) D будет иметь виртуальную таблицу, а Test не будет.

Peter 01.04.2022 07:23

Я думал, что наибольшее выравнивание следует использовать в любом случае, но на самом деле оно должно быть таким же, как и самый большой тип данных, верно?

ENTNEAZ 01.04.2022 09:25

Компилятор должен выбрать такое выравнивание, чтобы при создании массива структур все члены всех элементов были правильно выровнены. Это имеет мало общего с размером членов, больше с их требуемым выравниванием.

BoP 01.04.2022 09:30

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

BoP 01.04.2022 09:32

Размер пустого класса не равен 1, чтобы «избежать нулевого указателя», он равен 1, чтобы дать каждому объекту свое уникальное местоположение. (Если у вас есть массив A as[3], у вас не может быть &as[0] + 1 == &as[0] + 2.)

molbdnilo 01.04.2022 09:50

Хорошо, я думаю, я понял. Спасибо

ENTNEAZ 01.04.2022 10:05
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
9
75
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

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.

Другие вопросы по теме