Разве размер vptr на 64-битных компьютерах ** должен ** быть 64-битным?
Мне любопытно, почему размер vptr занимает 64 бита на 64-битных машинах и действительно ли это требуется в C++.
Все, что нужно сделать vptr, это указать на vtables, и поскольку vtables не может занимать слишком много памяти и может быть сгруппирован вместе, 32 бита должно быть более чем достаточно для их решения.
Сколько классов у вас в программе? 1000? 10000? Сколько виртуальных функций у них в среднем? Может быть 100? Если компилятор + компоновщик разместит все vtables последовательно, они не могут занять более нескольких МБ. Адресация конкретной таблицы с 32-битным индексом в "массив всех таблиц" должна работать.
Я даже говорю об этом из-за определенных небольших классов с виртуальными функциями; иногда я вижу огромные массивы объектов класса всего с двумя словами + vptr, и этот 64-битный vptr оказывает значительное влияние на использование памяти.
2 ответа
Нет, он не должен быть 64-битным. Но есть несколько причин, по которым это так:
- Существует вероятность того, что первый член класса нуждается в 64-битном выравнивании, поэтому в этом случае нет никакой выгоды
- Обычно vptrs не занимают значительную память
- И самый сильный аргумент: если vptr будет 32-битным индексом, то все вызовы виртуальных функций будут медленнее (из-за дополнительной ссылки на память) и будут генерировать больший код. Это просто не стоит того.
Обратите внимание, что есть модель памяти (ILP32, -mx32
switch для gcc), который редко используется, где указатели 32-битные, но могут использоваться 64-битные регистры.
Микрооптимизация памяти сейчас не в фокусе. Например, компилятор может свободно переупорядочивать элементы по спецификаторам доступа (так что заполнение может быть уменьшено), но ни один из известных мне компиляторов не делает этого.
Ваше подозрение верно, это действительно разрешено C++. 16 битов не могут быть реалистичными, хотя. И даже если бы все vtables были больше чем 4 ГБ, они обычно не были бы большими 4 миллиардами записей. Типичная стабильная запись составляет 64 бита, поэтому 4 миллиарда записей занимают 32 ГБ.