В C++, где в памяти помещенные функции класса?

Флажок enum тоже может работать, если вы сделаете его байтом enum:

[Flags] enum PesHeaders : byte { /* ... */ }
18
задан GEOCHET 1 June 2009 в 17:40
поделиться

9 ответов

Это не обязательно верно, что "каждому объекту - при создании - дадут пространство в "КУЧЕ" для членских переменных". Каждый объект, который Вы создаете, займет некоторое ненулевое место где-нибудь для его членских переменных, но где составил, как Вы выделяете сам объект. Если объект имеет автоматический (стек) выделение, так также будут его элементы данных. Если объект будет выделен на свободном хранилище ("куча"), то так также будут ее элементы данных. В конце концов, каково выделение объекта кроме того из его элементов данных?

, Если выделенный стеку объект содержит указатель или другой тип, который тогда используется для выделения на "куче", то выделение произойдет на "куче" независимо от того, где сам объект был создан.

Для объектов с виртуальными функциями, каждому выделят vtable указатель, как будто это был явно объявленный элемент данных в классе.

Что касается функций членства, код для тех вероятен не отличающийся от свободно-функционального кода с точки зрения того, где он входит в исполняемое изображение. В конце концов, функция членства является в основном бесплатной функцией с неявным "этот" указатель как его первый аргумент.

Наследование не изменяет большую часть ничего.

я не уверен, что Вы имеете в виду о DLLs получение их собственного стека. DLL не является программой и не должен иметь никакой потребности в стеке (или "куча"), как возражает, что это выделяет, всегда выделяются в контексте программы, которая имеет ее собственный стек и "кучу". То, что был бы код (текст), и сегменты данных в DLL действительно имеет смысл, хотя я не опытен в реализации таких вещей в Windows (который я предполагаю, что Вы используете, учитывая свою терминологию).

27
ответ дан 30 November 2019 в 07:18
поделиться

Код существует в сегменте текста, и сколько кода сгенерировано на основе классов, довольно сложно. Скучный класс без виртуального наследования якобы имеет некоторый код для каждой функции членства (включая тех, которые неявно создаются при исключении, такие как конструкторы копии) только однажды в сегменте текста. Размер любого экземпляра класса, как Вы заявили, обычно размер суммы членских переменных.

Затем это становится несколько сложным. Несколько проблем...

  • компилятор может, если он хочет или проинструктирован, встроенный код. Таким образом даже при том, что это могла бы быть простая функция, если это используется во многих местах и выбирается для встраивания, много кода может быть сгенерировано (распространение на всем протяжении кода программы).
  • Виртуальное наследование увеличивает размер полиморфных каждый участник. VTABLE (виртуальная таблица) скрывается наряду с каждым экземпляром класса с помощью виртуального метода, содержа информацию для отправки во время выполнения. Эта таблица может стать довольно большой, если у Вас есть много виртуальных функций или несколько (виртуальное) наследование. Разъяснение: VTABLE в классе, но указатели на VTABLE хранятся в каждом экземпляре (в зависимости от наследственной структуры типа объекта).
  • Шаблоны могут вызвать чрезмерное увеличение размера кода. Каждое использование шаблонного класса с новым набором шаблонных параметров может сгенерировать совершенно новый код для каждого участника. Современные компиляторы пытаются свернуть это как можно больше, но это твердо.
  • выравнивание/дополнение Структуры может заставить простые экземпляры класса быть больше, чем Вы ожидаете, поскольку компилятор дополняет структуру для целевой архитектуры.

При программировании, используйте sizeof оператор для определения размера объекта - никогда твердый код. Используйте грубую метрику "Суммы членского размера переменной + некоторый VTABLE (если это существует)" при оценке, как дорогие большие группы экземпляров будут и не волнуются чрезмерно о размере кода. Оптимизируйте позже, и если какая-либо из неочевидных проблем возвратится для значения чего-то, то я буду скорее удивлен.

6
ответ дан 30 November 2019 в 07:18
поделиться

Хотя некоторыми аспектами этого является зависимый поставщика компилятора. Весь скомпилированный код входит в раздел памяти в большинстве систем, названных 'текстом'. это является отдельным от обоих "куча" и разделы стека (четвертый раздел, 'данные', содержит большинство констант). Инстанцирование многих экземпляров класса подвергается пространству во время выполнения только для его переменных экземпляра, не для любой из его функций. При использовании виртуальных методов Вы получите дополнительный, но маленький, бит памяти, отложенной для виртуальной таблицы поиска (или эквивалентный для компиляторов, которые используют некоторое другое понятие), но его размер определяется количеством виртуальных раз методов количество виртуальных классов и независим от количества экземпляров во времени выполнения

, Это верно для статически и динамично связанный код. Фактический код все жизни в 'текстовом' регионе. Большинство операционных систем на самом деле может совместно использовать код dll через несколько приложений, поэтому если несколько приложений используют тот же dll's, только одна копия находится в памяти, и оба приложения могут использовать его. Очевидно, нет никаких дополнительных сбережений от общей памяти, если только одно приложение использует связанный код.

2
ответ дан 30 November 2019 в 07:18
поделиться

Вы не можете полностью точно сказать, сколько памяти класс или X объектов поднимут в RAM.

Однако для ответа на вопросы Вы корректны, что код существует только в одном месте, он никогда не "выделяется". Код поэтому на класс, и существует, создаете ли Вы объекты или нет. Размер кода определяется Вашим компилятором, и даже тогда компиляторам можно часто говорить оптимизировать размер кода, ведя к отличающимся результатам.

Виртуальные функции не отличаются, сохраняют (маленькие) добавленные издержки таблицы виртуальных методов, которая обычно на класс.

Относительно DLLs и других библиотек... правила не отличаются в зависимости от того, куда код прибыл из, таким образом, это не фактор в использовании памяти.

1
ответ дан 30 November 2019 в 07:18
поделиться

если скомпилировано как 32 бита. тогда sizeof (Панель) должен уступить 4. Нечто должно добавить 10 байтов (2 ints + 2 символа).

, Так как Нечто наследовано от Панели. Это - по крайней мере 4 + 10 байтов = 14 байтов.

GCC имеет атрибуты для упаковки структур, таким образом, нет никакого дополнения. В этом случае 100 записей подняли бы 1 400 байтов + крошечные издержки для выравнивания выделения + немного служебные из для управления памятью.

, Если никакой упакованный атрибут не определяется, это зависит от выравнивания компиляторов.

, Но это не рассматривает, сколько vtable память поднимает и размер скомпилированного кода.

1
ответ дан 30 November 2019 в 07:18
поделиться

Ваша оценка точна в основном случае, который Вы представили. Каждый объект также имеет vtable с указателями для каждой виртуальной функции, поэтому ожидайте ценность дополнительного указателя памяти для каждой виртуальной функции.

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

Так же, как в c можно использовать sizeof (имя класса/тип данных) оператор для получения размера в байтах класса.

0
ответ дан 30 November 2019 в 07:18
поделиться

Да, правильно, код не дублирован, когда экземпляр объекта создается. Насколько виртуальные функции идут, надлежащий вызов функции определяется с помощью vtable, но это не влияет на создание объекта по сути.

DLLs (общие/динамичные библиотеки в целом) с отображенной памятью в пространство памяти процесса. Каждая модификация продолжена как Копия на записи (COW): единственный DLL загружается только однажды в память, и для каждой записи в изменяемое пространство копия того пространства создается (обычно размера страницы).

0
ответ дан 30 November 2019 в 07:18
поделиться

Очень трудно дать точный ответ на yoour вопрос, поскольку это - implementtaion иждивенец, но приближенные значения для 32-разрядной реализации могли бы быть:

int Bar::mProtectedVar;    // 4 bytes
int Foo::mPublicVar;        // 4 bytes
char Foo::mPublicVar2;     // 1 byte

существуют проблемы allgnment здесь, и заключительное общее количество может составить 12 байтов. У Вас также будет vptr - говорят еще 4 байта. Таким образом, общий размер для данных составляет приблизительно 16 байтов за экземпляр. Невозможно сказать, сколько пространства код поднимет, но Вы корректны в размышлении, что существует только одна копия кода, совместно использованного всеми экземплярами.

, Когда Вы спрашиваете

, я предполагаю, что dlls получают свой собственный стек, "кучу", сегменты кода и сегменты данных.

ответ Th - то, что действительно нет большого различия между данными в DLL и данными в приложении - в основном они совместно используют все между ними, Это должно быть так, когда Вы думаете о приблизительно этом - если у них были различные стеки (например), как вызовы функции могли работать?

0
ответ дан 30 November 2019 в 07:18
поделиться

Информация, приведенная выше, очень мне помогает и дала мне некоторое представление о структуре памяти C ++. Но я хотел бы добавить, что независимо от того, сколько виртуальных функций в классе, всегда будет только 1 VPTR и 1 VTABLE на класс. В конце концов, VPTR указывает на VTABLE, поэтому нет необходимости в более чем одном VPTR в случае нескольких виртуальных функций.

1
ответ дан 30 November 2019 в 07:18
поделиться
Другие вопросы по тегам:

Похожие вопросы: