TGViewer
C++95 C++95 @cxx95 · 1.51K subscribers
Post #88 1.51K
#compiler

Теория девиртуализации 😶

Виртуальные функции обычно работают через vtable. Если метод виртуальный, то вместо вызова точно известного метода, в рантайме вычисляется адрес метода, который зависит от динамического типа объекта.

Однако в некоторых случаях компилятор может "доказать", что он точно "знает" метод, который надо вызвать, несмотря на то, что метод виртуальный 😐

Два простых примера: класс без final (нет оптимизации), класс с final (есть оптимизация - девиртуализация). Девиртуализованный вариант меньше дергает память.
void CallDo(TDerived& obj) {
obj.Do(); // будет ли девиртуализация?
}

Компилятор считает, что можно девиртуализовать вызов в таких случаях:
1️⃣ Метод класса помечен как final.
Смысл в том, что даже в случае работы с объектами TDerived*/TDerived& (которые могут указывать на наследника TDerived) нужный метод будет одним и тем же, как его определил класс TDerived.
struct TDerived : IBase {
void Do() final override; // слово `final` тут
};

2️⃣ Класс является финальным. Смысл в том, что указатель на этот класс не будет указывать на какого-то наследника, который что-то мог бы переопределить, потому что у такого класса просто не может быть наследников.
struct TDerived final : IBase { // слово final тут
void Do() override;
};

Однако есть еще одно условие, когда класс считается финальным - если у него финальный деструктор 😁 Этот прикол я обнаружил в исходнике Clang.
struct TDerived : IBase {
~TDerived() final = default; // слово final тут
void Do() override;
};

3️⃣ Мы работаем с объектом класса, а не с указателем на класс. В этом случае точный класс объекта известен на этапе компиляции.
TDerived derived;
derived.Do(); // это же TDerived, инфа 100%

4️⃣ Объект является prvalue. В C++ есть укуренная классификация объектов, где prvalue (pure value) это грубо говоря выражение которое создает новый объект. Смысл в том, что в этом случае тоже известен точный класс объекта на этапе компиляции.
TDerived MakeDerived(); // просто функция
// ...
MakeDerived().Do(); // здесь будет девиртуализация
TDerived{}.Do(); // здесь тоже девиртуализация

На этом всё! Эта оптимизация логичная и скучная, потому что никаких чудес ожидать не приходится. Смысл в том, чтобы доказать что TDerived/TDerived&/TDerived* указывает именно на объект TDerived, а не на какой-то его потомок.

В реальном мире девиртуализация отрабатывает нечасто, так как надо, чтобы совпали два редких покемона кейса, оба противоречат ООП:
(1) работа с TDerived* вместо IBase*;
(2) Класс TDerived или нужный метод финальный (не помню когда в последний раз писал final).

Если вы хотите почитать про девиртуализацию "с нуля" с картинками, то есть крутой лонгрид.

Девиртуализация в C++ не гарантирована. В большинстве своем правила выше работают, но не всегда. В каких-то случаях оптимизировать вызовы виртуальных методов запрещено.

Например, в Apple macOS👩‍💻 есть Kext (Kernel Extension) - расширения ядра, запускающие то или иное несовместимое с оригинальным маком оборудование. Особенность этих Kext в том, что они могут в рантайме менять vtable, поэтому нельзя делать оптимизации, которые обходят обращение к vtable. В Clang есть флаг -fapple-kext для такой настройки.

А в "обычных" окружениях vtable лежат в секциях наподобии .rodata. Эта секция защищена на уровне операционной системы - программа обычно сразу падает при попытке сделать туда какую-нибудь запись в рантайме.
  • 👍 21
  • 🔥 5
  • 🖕 1
More from @cxx95
  1. Sep 21, 2026#offtop Великое Мидревью 💼 В последнее время темы про C++ накапливаются медленно, и то та…
  2. Jun 17, 2026#jostik Обзор жостиков C++ 💼 (номер 5️⃣) В последние несколько месяцев совсем ничего не п…
  3. Jun 17, 2026document post
  4. Jan 7, 2026#compiler #ai На фото из марта 2024 - мерч с работы, это кофта и набор нашивок, которые мо…
  5. Jan 7, 2026document post
  6. Aug 18, 2025#books Текст в окружности - первые слова в опере (услышать) 🎤 📕 Обзор на книгу про памят…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →