Сколько байтов не встроенный не виртуальный метод добавляет к экземпляру класса? С++

Возьмем, к примеру, эти два класса. (С++)

class B1 {
public:

};

class B2 {
public:
  void f0 () {}
  void f1 () {}
};

Насколько больше будет класс B2 в памяти по сравнению с B1

Я чувствую, что это один из двух ответов.

один 4-байтовый указатель типа int в 32-битных системах методом PER.

Или что-то похожее на то, что происходит с таблицами виртуальных методов http://en.wikipedia.org/wiki/Virtual_method_table

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

Спасибо.

Редактировать: спасибо за все замечательные и быстрые ответы :) (также помеченный ответ)


person mmacdermaid    schedule 05.03.2012    source источник
comment
Простой трюк: протестируйте его в своем компиляторе и посмотрите, сможете ли вы опровергнуть свою гипотезу.   -  person Kerrek SB    schedule 05.03.2012
comment
Обратите внимание, что даже если вы попробуете, и это не опровергнет вашу гипотезу, это не означает, что ваша гипотеза верна.   -  person André Caron    schedule 05.03.2012
comment
возможный дубликат В С++, где в памяти помещаются функции класса? (благодаря @Sid за его нахождение)   -  person Ben Voigt    schedule 05.03.2012


Ответы (2)


Нет.

Невиртуальные методы не увеличивают размер класса.

Что касается virtual методов, то только первый добавленный в класс увеличит его размер, все последующие - нет.

Тот факт, что это inline или нет, также не влияет на размер класса.

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

B2 b;
b.f0();

компилятор может просто сгенерировать код для вызова B2::f0(). Указатель this передается как внутренний параметр, чтобы метод знал, с каким экземпляром класса работать.

Для простого теста:

class B1 {
public:

};

class B2 {
public:
  void f0 () {}
  void f1 () {}
};

//...
assert( sizeof(B1) == sizeof(B2) );
person Luchian Grigore    schedule 05.03.2012
comment
Как бы вы доказали, что это верно в C++ и почему это так? - person mmacdermaid; 05.03.2012
comment
@mmacdermaid Я уже объяснил, почему это так: 1) в этом нет необходимости, так как методы не нуждаются в динамической привязке (как в случае с виртуальными методами) 2) огромная трата памяти. Что касается доказательства, вы можете сравнить размер ваших 2 классов. - person Luchian Grigore; 05.03.2012
comment
Добавьте метод и используйте sizeof для вычисления до и после размера. - person Sid; 05.03.2012
comment
Я уловил ваш ответ до того, как вы его отредактировали. Спасибо за обновления. - person mmacdermaid; 05.03.2012
comment
@mmacdermaid: я не уверен, что такое поведение действительно требуется стандартом, поскольку (как сообщается) можно реализовать интерпретатор C++. Однако во всех практических реализациях (и, следовательно, во всех популярных компиляторах) адрес метода жестко запрограммирован компилятором во время компиляции и никогда не нуждается в поиске/доступе/вычислении во время выполнения, поэтому нет необходимости для хранения указателя для поиска адреса. - person André Caron; 05.03.2012
comment
@AndréCaron, это хороший момент. Я не удосужился заглянуть в стандарт, но я предполагаю, что если кто-то достаточно умен, чтобы написать компилятор, у него никогда не будет невиртуальных методов, увеличивающих размер объекта. - person Luchian Grigore; 05.03.2012

Ответ Лучиана правильный. Я просто хочу добавить, что код хранится в текстовом сегменте, который отличается от того, где находятся данные (сегмент данных). Следовательно, единственные временные методы, влияющие на размер объекта, — это когда они являются виртуальными методами, что вынуждает помещать vptr внутрь объекта. Прочтите это, чтобы лучше понять часть сегментов: В C++ где в памяти помещаются функции класса?

person Sid    schedule 05.03.2012
comment
Поскольку это не ответ, я предлагаю вам оставить комментарий. Хорошая ссылка, кстати! - person André Caron; 05.03.2012
comment
Это хорошая ссылка, которая, кажется, достаточно полно охватывает этот вопрос, чтобы пометить его как обман. - person Ben Voigt; 05.03.2012