Сравнение виртуальных функций в С++ и виртуальных таблицах в C, делают ли компиляторы в целом (и для достаточно больших проектов) как хорошая работа при девиртуализации?
Наивно, похоже, что виртуальные функции в С++ имеют немного больше семантики, поэтому может быть проще девиртуализировать.
Обновление: Mooing Duck, упомянутый в стиле девиртуализированных функций. Быстрая проверка показывает пропущенные оптимизации с виртуальными таблицами:
struct vtab {
int (*f)();
};
struct obj {
struct vtab *vtab;
int data;
};
int f()
{
return 5;
}
int main()
{
struct vtab vtab = {f};
struct obj obj = {&vtab, 10};
printf("%d\n", obj.vtab->f());
}
Мой GCC не будет встраивать f, хотя он вызывается непосредственно, т.е. девиртуализован. Эквивалент в С++,
class A
{
public:
virtual int f() = 0;
};
class B
{
public:
int f() {return 5;}
};
int main()
{
B b;
printf("%d\n", b.f());
}
делает даже встроенный f. Итак, есть первое отличие между C и С++, хотя я не думаю, что добавленная семантика в версии С++ имеет значение в этом случае.
Обновление 2: для девиртуализации в C компилятор должен доказать, что указатель функции в виртуальной таблице имеет определенное значение. Для девиртуализации в С++ компилятор должен доказать, что объект является экземпляром определенного класса. Казалось бы, доказательство сложнее в первом случае. Тем не менее, виртуальные таблицы обычно изменяются только в очень немногих местах, а самое главное: только потому, что они выглядят сложнее, это не значит, что компиляторы не так хороши в этом (иначе вы могли бы утверждать, что xoring обычно быстрее, чем добавление двух целые числа).