Динамический полиморфизм против std::variant на указателях: Разрушаем мифы о скорости std::visit
В экосистеме современного C++ прочно укоренилось мнение: классический динамический полиморфизм через виртуальные функции ( vtable ) — это устаревший, медленный и недружелюбный к кэшу процессора механизм. В качестве «серебряной пули» модно предлагать связку std::variant и std::visit . По интернету кочуют статьи, утверждающие, что std::visit выполняет диспетчеризацию за фиксированное время O(1) и полностью уничтожает старый добрый ООП-подход. Но в таких сравнениях авторы часто совершают методологическую ошибку: они противопоставляют вектор указателей std::vector<Base*> вектору сырых объектов std::vector<std::variant> . Разумеется, std::variant побеждает, но не из-за механики вызова, а благодаря стопроцентной локальности данных в кэше процессора. Давайте снимем розовые очки, уравняем условия и изолируем саму механику вызовов. Представьте реальный сценарий: объекты тяжелые, создаются динамически в разное время и разбросаны по куче (Heap), а мы оперируем массивами их адресов. Мы столкнем лоб в лоб std::vector<Base*> и std::vector<std::variant<TypeA, TypeB, TypeC>*> в условиях раздельной компиляции (когда оптимизатор -O2 не видит тела функций и не может применить тотальный инлайнинг).










