Обеспечивает ли ключевое слово final оптимизацию, если все производные классы известны во время компиляции? - PullRequest
0 голосов
/ 25 октября 2019

Теоретически, использование ключевого слова final в объявлении виртуального метода в C ++ 11 и далее позволяет встраивать метод.

Это можно увидеть здесь.

Однако я подозреваю, что на практике, если во время компиляции известно, что нет никаких производных классов, переопределяющих этот метод, компилятор может вставить для нас final и встроить метод.

Однако, добавив это в проводник компилятора, вы увидите, что он все еще обеспечивает оптимизацию.

Почему это так?

Ответы [ 2 ]

2 голосов
/ 25 октября 2019

конечное ключевое слово в объявлении виртуального метода в C ++ 11 и далее позволяет встраивать метод

Не inlining, но де-виртуализация.

Однако я подозреваю, что на практике, если во время компиляции известно, что нет никаких производных классов, переопределяющих этот метод, [..]

Вы не можете знать во время компиляции, что естьникакие другие производные классы (если класс не final): пользователь или другой TU может предоставить некоторые. потенциально это может быть сделано по ссылке, при условии отсутствия динамической загрузки ...

[..] компилятор может вставить финал для нас и встроить метод. Однако, добавив это в проводник компилятора, вы увидите, что онпо-прежнему обеспечивает оптимизацию.

 struct A {
     virtual void f() {}
 };

struct B : public A {
     void f() final override {}
 };

struct C : public A {
     void f() override {}
 };
void foo(B& b) { b.f(); }
void bar(C& c) { c.f(); }
C::f():
        rep ret
foo(B&):
        rep ret
bar(C&):
        mov     rax, QWORD PTR [rdi]
        mov     rax, QWORD PTR [rax]
        cmp     rax, OFFSET FLAT:C::f()
        jne     .L6
        rep ret
.L6:
        jmp     rax

Почему это так?

Здесь компилятор встраивает вызов C::f (rep ret) для случая, когда динамический типc - это C: тогда вместо вызова C::f он делает то, что делает C::f (-> ничего).

виртуальный вызов все еще является вызовом для другого динамического типа (jmp rax).

0 голосов
/ 25 октября 2019

При оптимизации final влияет только на то, может ли компилятор доказать, что является производным типом во время компиляции. Если тип известен, то нет необходимости помогать компилятору знать его.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...