Давайте посмотрим на расположение классов в двух случаях.
Без виртуального у вас есть два базовых класса («X» и «Y») с целым числом каждый, и каждый из этих классов интегрировал в себя базовый класс «Base», который также имеет целое число. Это 4 целых числа по 32 бита каждое, всего 16 байт.
Offset Size Type Scope Name
0 4 int Base a
4 4 int X x
8 4 int Base a
12 4 int Y y
16 size (Z members would come at the end)
(Изменить: я написал программу на DJGPP, чтобы получить макет и настроил таблицу, чтобы учесть это.)
Теперь поговорим о виртуальных базовых классах: они заменяют фактический экземпляр класса указателем на общий экземпляр. Ваш класс «Z» имеет только один «базовый» класс, и оба экземпляра «X» и «Y» указывают на него. Следовательно, у вас есть целые числа в X, Y и Z, но у вас есть только одно Z. Это означает, что у вас есть три целых числа или 12 байтов. Но у X и Y также есть указатель на общий Z (иначе они не знали бы, где его найти). На 32-битной машине два указателя добавят дополнительные 8 байтов. Это всего 20, которые вы видите. Схема памяти может выглядеть примерно так (я не проверял это ... у ARM есть пример, где порядок - X, Y, Z, затем Base):
Offset Size Type Scope Name Value (sort of)
0 4 Base offset X ? 16 (or ptr to vtable)
4 4 int X x
8 4 Base offset Y ? 16 (or ptr to vtable)
12 4 int Y y
16 4 int Base a
20 size (Z members would come before the Base)
Таким образом, разница в памяти - это сочетание двух вещей: на одно целое число меньше и на два указателя больше. В отличие от другого ответа, я не верю, что vtables платят какой-либо (редактировать) прямой (/ редактировать) ролл в этом, поскольку нет виртуальных функций.
Изменить: ppinsider предоставил дополнительную информацию о случае gcc, в котором он демонстрирует, что gcc реализует указатель на виртуальный базовый класс, используя в противном случае пустую vtable (то есть без виртуальных функций). Таким образом, если бы были виртуальные функции, не потребовался бы дополнительный указатель в экземпляре класса, требующий больше памяти. Я подозреваю, что обратная сторона - это дополнительное косвенное обращение к базовому классу.
Мы могли бы ожидать, что все компиляторы сделают это, но, возможно, нет. На странице 225 ARM обсуждаются виртуальные базовые классы без упоминания vtables. Страница 235 специально обращается к «виртуальным базовым классам с виртуальными функциями» и имеет диаграмму, показывающую структуру памяти, где есть указатели из частей X и Y, которые отделены от указателей на vtable. Я бы посоветовал никому не считать само собой разумеющимся, что указатель на Base будет реализован в виде таблицы.
person
markets
schedule
28.12.2008