Как хранятся структуры в памяти?

195
17 февраля 2019, 00:40

Прочитал, что поля структуры хранятся в памяти последовательно(в порядке объявления) (+- платформ.зависимое выравнивание). Вопрос такой: как влияют методы в структурах на их расположение в памяти? Предположим, есть структура вида:

struct my_Struct{
double n;
void meth();
char ch;
    }

Как экземпляр этой структуры (а именно его поля) будут расположены в памяти? И ещё, применимы ли все знания по структурам(и их расположению в памяти) к классам? И есть ли какая-то разница (с точки зрения памяти) между обычными методами и перегрузками / конструкторами / деструкторами?

Answer 1

Во-первых, как правильно заметили в комментариях, в С++ структур нет. Ключевое слово struct создает классы, в которых поля и родители по умолчанию публичные. Какой-то другой разницы между struct и class, с точки зрения стандарта, насколько я знаю, нет.

Поля классов хранятся в порядке объявления только если спецификатор доступа (public/private/protected) у них одинаковый.

Если спецификатор доступа одинаковый, то из двух полей в памяти идет раньше то, которое в определении класса написано выше. Если спецификатор доступа у двух полей разный, то компилятор вправе расположить их относительно друг друга как угодно.

В частности, соответствующий стандарту компилятор может располагать все поля в памяти по порядку, игнорируя спецификаторы доступа. А может сложить в кучку отдельно private, protected и public. Могут быть какие-то другие варианты.

Пруф: [class.mem]/19

Non-static data members of a (non-union) class with the same access control are allocated so that later members have higher addresses within a class object. The order of allocation of non-static data members with different access control is unspecified. Implementation alignment requirements might cause two adjacent members not to be allocated immediately after each other; so might requirements for space for managing virtual functions and virtual base classes.

У каждого экземпляра одного класса, очевидно, свой набор из всех нужных полей.

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

Обычно методы реализуются так же, как и обычные функции, но с добавленным невидимым параметром this. Так что нет смысла в каждом экземпляре хранить какую-то информацию о методах, не считая vtable pointer.

*Хотя разницы между class и struct быть не должно, и хотя не виртуальные методы на размер класса влиять не должны, мне у нас на SO недавно попался пример, в котором GCC с определенными настройками убирал выравнивание из struct как только к нему добавляли один любой метод, либо когда struct меняли на class. Видимо для совместимости с каким-то С-шным компилятором. Если кто-то найдет больше информации по этой теме, буду благодарен.

Answer 2
  1. Методы никак не влияют на расположение в памяти (посмотреть). Методы априори не могут занимать память объектов (методы ведь не создаются для каждого объекта отдельно). Метод - (на низком уровне) это функция для которой просто передается указатель this с помощью регистра процессора. Из ранее приведенной ссылки:

lea rax, [rbp-12] - взятие адреса объекта (начала последовательности байт принадлежащих объекту) и помещение его в регистр. Далее метод будет работать как обычная функция, зная, что в нужном регистре хранится указатель на текущий объект.

  1. Различие между структурой и классом только в доступности по умолчанию: структуры - public, классы - private (все члены по умолчанию имеют указанный спецификатор доступа) (class).

  2. Перегруженные функции - это разные функции (каждая из них имеет собственный адрес). Какая именно функция будет вызвана компилятор решит во время компиляции (в отличии от виртуальных методов). Посмотреть.

READ ALSO
Функция gets_s не работает

Функция gets_s не работает

Перемещение функции gets_s из тела функции main в тело функции INPUT приводит к ошибке"Отсутствуют экземпляры перегруженная функция 'gets_s' соответствующие...

1224
Задача с покупкой продуктов

Задача с покупкой продуктов

Падает задача выдавая Runtime errorПри этом на тестовом примере работает правильно

174
Ошибка Index out of range в QVector

Ошибка Index out of range в QVector

pointsOfGrid заполняются нормально, не мусором, maxRadius - аналогичноОшибка возникает при попытке установить QCPCurveData ума не приложу что делать

234
копирование двумерного массива

копирование двумерного массива

Код нижеОн делит строку на маленькие подстрочки меньшего размера (чанки фиксированной величины, для примера 10), получается двумерный массив,...

300