Страницы

Поиск по вопросам

пятница, 20 декабря 2019 г.

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

#cpp #память #структуры


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

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


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


Ответы

Ответ 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. Видимо для совместимости с каким-то С-шным компилятором. Если кто-то найдет больше информации по этой теме, буду благодарен.

Ответ 2



Методы никак не влияют на расположение в памяти (посмотреть). Методы априори не могут занимать память объектов (методы ведь не создаются для каждого объекта отдельно). Метод - (на низком уровне) это функция для которой просто передается указатель this с помощью регистра процессора. Из ранее приведенной ссылки: lea rax, [rbp-12] - взятие адреса объекта (начала последовательности байт принадлежащих объекту) и помещение его в регистр. Далее метод будет работать как обычная функция, зная, что в нужном регистре хранится указатель на текущий объект. Различие между структурой и классом только в доступности по умолчанию: структуры - public, классы - private (все члены по умолчанию имеют указанный спецификатор доступа) (class). Перегруженные функции - это разные функции (каждая из них имеет собственный адрес). Какая именно функция будет вызвана компилятор решит во время компиляции (в отличии от виртуальных методов). Посмотреть.

Комментариев нет:

Отправить комментарий