2014-02-10 4 views
4

Не помню, где я его видел сейчас, но где-то я читал, что динамический полиморфизм не позволяет компилятору делать различные оптимизации.Пример полиморфизма, предотвращающего оптимизацию компилятора?

Кроме того, может ли кто-нибудь углубить меня любыми примерами таких «пропущенных» возможностей оптимизации, которые полиморфизм мешает компилятору создавать?

+0

Конечно, вставки. И инициализированные «константы». Не могу придумать ничего другого. –

+0

Я бы сказал, что эти пропущенные оптимизации - это последствия неудачной вставки. Я думаю, что это самая большая потеря, и это, по-видимому, самая большая мотивация девиртуализации. – Ali

ответ

0

По крайней мере, в C++ полиморфные объекты должны быть в виде указателей или ссылок. Иногда это предотвращает возможность помещать их в переменные стека или типы списка, вам нужно использовать List. Переменные хранилища резервные динамические распределения и т. Д.

Вызов Poly.vmethod() всегда разрешается во время компиляции, даже если vmethod() является виртуальным, а Poly-> vmethod() - с таблицей виртуальных методов. (Ну, если этот метод является виртуальным, он должен быть полиморфным. Статические методы статически разрешаются в любом случае.)

Оптимизация возвращаемого значения (RVO) - это еще один трюк, который не имеет места при возврате указателей или ссылок. RVO обычно реализуется путем передачи скрытого параметра: указателя на область памяти, заполненного «возвращенным» объектом. Размер и тип этого региона должны быть прекрасно известны во время компиляции.

+0

Не могли бы вы рассказать о своем комментарии RVO? – user997112

+0

Полиморфные объекты * могут * жить в стеке, в коллекциях по значению и т. Д., Поскольку указатели и ссылки могут указывать на любую память. Например, 'void f (Base & o) {o.vmethod()}' можно вызвать следующим образом: 'Derived on_stack; F (on_stack); '. – delnan

2

С:

Derived d; 
d.vMethod(); // that will call Derived::vMethod statically (allowing inlining). 

С (если ни одна из Derived или Derived::vMethod не объявлен final в C++ 11):

void foo(Derived& d) 
{ 
    d.vMethod(); // this will call virtually vMethod (disallowing inlining). 
} 

Виртуального вызов имеет дополнительную стоимость (как косвенность через виртуальные таблицы).

C++ 11 представляет ключевое слово final, которое может превратить последний пример в статический вызов.

+0

Косвенный вызов также обычно более дорогой с точки зрения прогноза цели. При статическом вызове целевой адрес может быть вычислен в интерфейсе процессора, поэтому целевое неверное предсказание может быть скорректировано раньше. Кроме того, аппаратное прогнозирование переменных целей является более сложным (когда оно не просто прогнозирует то же, что и для последней встречи с инструкцией), поэтому иногда неточно в простых процессорах и предсказание очень сложно для «случайных» целей. –

Смежные вопросы