Виртуальные функции очень эффективны. Предполагая 32-битные указатели, объем памяти составляет примерно:
classptr -> [vtable:4][classdata:x]
vtable -> [first:4][second:4][third:4][fourth:4][...]
first -> [code:x]
second -> [code:x]
...
classptr указывает на память, которая обычно находится в куче, иногда в стеке, и начинается с четырехбайтового указателя на виртуальную таблицу для этого класса. Но важно помнить, что сама таблица не выделяет память. Это статический ресурс, и все объекты одного и того же типа класса будут указывать на одно и то же место в памяти для своего массива vtable. Вызов разных экземпляров не приведет к извлечению разных областей памяти в кэш L2.
Этот пример из msdn показывает виртуальную таблицу для класса A с виртуальными func1, func2 и func3. Ничего больше, чем 12 байтов. Существует большая вероятность того, что таблицы с различными классами также будут физически смежными в скомпилированной библиотеке (вы должны убедиться, что это вас особенно беспокоит), что может микроскопически повысить эффективность кэша.
CONST SEGMENT
??_7A@@6B@
DD FLAT:?func1@A@@UAEXXZ
DD FLAT:?func2@A@@UAEXXZ
DD FLAT:?func3@A@@UAEXXZ
CONST ENDS
Другая проблема производительности - накладные расходы при вызове через функцию vtable. Это тоже очень эффективно. Почти идентичен вызову не виртуальной функции. Снова из примера из MSDN :
; A* pa;
; pa->func3();
mov eax, DWORD PTR _pa$[ebp]
mov edx, DWORD PTR [eax]
mov ecx, DWORD PTR _pa$[ebp]
call DWORD PTR [edx+8]
В этом примере ebp, базовый указатель кадра стека, имеет переменную A* pa
со смещением нуля. Регистр eax загружается со значением в location [ebp], поэтому он имеет A *, а edx загружается со значением в location [eax], поэтому он имеет класс A vtable. Затем ecx загружается с помощью [ebp], поскольку ecx представляет «this», теперь он содержит A *, и, наконец, выполняется вызов значения в местоположении [edx + 8], которое является третьим адресом функции в vtable. *
Если бы этот вызов функции не был виртуальным, mov eax и mov edx не были бы необходимы, но разница в производительности была бы неизмеримо мала.