Как выделяется память под классы, выделяется ли она при определении класса?
Как выделяется память под классы, выделяется ли она при определении класса и при создании объекта класса?
Ответы (3 шт):
Так как C++ - сложный (очень) язык со множеством реализаций на разных архитектурах и агрессивной оптимизацией, рассмотрение всех нюансов оперирования с памятью растянется на длиннопост (который будет, фактически, плохим переводом львиной доли Стандарта).
Ниже я приведу самые примитивные примеры, которых достаточно для базового понимания ситуации. Оно годится для ответа в школе/вузе, но с ним может быть трудно на собеседовании, особенно если вам попадется language lawyer
При определении - нет (если совсем точно - это зависит от компилятора и его настроек). При объявлении экземпляра - есть три варианта.
Все дальнейшие примеры - это просто середина тела какой-то функции:
Class clazz;- экземпляр создастся на стекеClass* clazz = new Class()- создастся на кучеClass* clazz = new(ptr) Class()- создастся по адресу ptr - Placement New (куда показывает ptr - это уже забота программиста)
Также запись Class clazz; - может встретится как поле структуры/класса, но в таком случае память будет выделяться / удаляться в зависимости от жизни экземпляра структуры/класса.
При компиляции определения класса создаются три вещи: код методов, VTBL если есть виртуальные методы, RTTI если его не отключили при компиляции. Вся эта информация попадает в исполнимый модуль и занимает место в памяти. Её объём во время работы программы не меняется.
Экземпляры класса тоже потребляют память. Каждый раз когда вы создаёте новый экземпляр вы обязаны предоставить ему память в которой он будет существовать.
Выделение памяти можно разделить на две большие категории:
Память распределяемая на этапе компиляции: объекты, содержимое которых известно на этапе компиляции (константы), машинный код функций, различная служебная информация, как то таблицы виртуальных методов, таблицы с информацией о типах, таблицы обработчиков исключений и т.п. Все это попадает в исполняемый файл и память под это все сразу выделяется системой при запуске приложения.
Память, распределяемая на этапе выполнения программы: объекты, содержимое которых не известно на этапе компиляции. В этом случае выделение памяти может определяться:
Компилятором - для всех объектов, имеющих время хранение automatic, static, thread local (то бишь созданных без оператора new).
Программистом - для всех объектов, имеющих время хранения dynamic (то бишь созданных посредством оператора new). В этом случае опять возможны два варианта:
Выделение памяти происходит с использованием глобальной или перегруженной функции выделения памяти (обычный синтаксис оператора new).
Выделения памяти не происходит, объект размещается в указанном существующем буфере (синтаксис placement new).