Незалежно від компілятора, ви завжди можете заощадити на час виконання, якщо можете дозволити це зробити
if (typeid(a) == typeid(b)) {
B* ba = static_cast<B*>(&a);
etc;
}
замість
B* ba = dynamic_cast<B*>(&a);
if (ba) {
etc;
}
Перший включає лише одне порівняння std::type_info
; останнє обов'язково передбачає обхід дерева спадщини плюс порівняння.
Минулого ... як усі кажуть, використання ресурсів є специфічним для впровадження.
Я погоджуюся з коментарями всіх інших, що подавець повинен уникати RTTI з дизайнерських причин. Однак є вагомі причини використовувати RTTI (головним чином через boost :: any). Зважаючи на це, корисно знати його фактичне використання ресурсів у загальних реалізаціях.
Нещодавно я провів ряд досліджень RTTI в GCC.
tl; dr: RTTI в GCC використовує незначний простір і typeid(a) == typeid(b)
дуже швидко працює на багатьох платформах (Linux, BSD і, можливо, вбудовані платформи, але не mingw32). Якщо ви знаєте, що завжди будете на благодатній платформі, RTTI дуже близький до безкоштовного.
Подрібнені деталі:
GCC вважає за краще використовувати певний "нейтральний до продавця" C ++ ABI [1] і завжди використовує цей ABI для цілей Linux та BSD [2]. Для платформ, які підтримують цей ABI, а також слабкий зв'язок, typeid()
повертає послідовний та унікальний об'єкт для кожного типу, навіть через динамічні межі зв’язку. Ви можете протестувати &typeid(a) == &typeid(b)
або просто покластися на те, що портативний тест typeid(a) == typeid(b)
насправді просто порівнює внутрішнє покажчик.
У кращому ABI GCC клас vtable завжди містить вказівник на структуру RTTI на тип, хоча він може не використовуватися. Таким чином, typeid()
сам виклик повинен коштувати стільки, скільки будь-який інший Vtable Lookup (такий же, як виклик функції віртуального члена), а підтримка RTTI не повинна використовувати додаткового місця для кожного об'єкта.
З того, що я можу зробити, структури RTTI, використовувані GCC (це всі підкласи std::type_info
), містять лише кілька байтів для кожного типу, окрім назви. Мені не зрозуміло, чи є імена у вихідному коді навіть із -fno-rtti
. Так чи інакше, зміна розміру складеного двійкового файлу має відображати зміну використання пам’яті під час виконання.
Швидкий експеримент (з використанням GCC 4.4.3 на 64-розрядному Ubuntu 10.04) показує, що -fno-rtti
насправді збільшується двійковий розмір простої програми тестування на кілька сотень байт. Це відбувається послідовно в комбінаціях -g
та -O3
. Я не впевнений, чому розмір збільшився б; одна можливість полягає в тому, що STL-код GCC поводиться по-різному без RTTI (оскільки винятки не працюватимуть).
[1] Відомий як Itanium C ++ ABI, задокументований на веб- сайті http://www.codesourcery.com/public/cxx-abi/abi.html . Імена жахливо заплутані: ім'я посилається на оригінальну архітектуру розробки, хоча специфікація ABI працює на багатьох архітектурах, включаючи i686 / x86_64. Коментарі у внутрішньому джерелі GCC та коді STL позначають Itanium як "новий" ABI на відміну від "старого", який вони використовували раніше. Гірше, що "новий" / Itanium ABI посилається на всі версії, доступні через-fabi-version
: "старий" ABI передував цій версії. GCC прийняв Itanium / verioned / "новий" ABI у версії 3.0; "старий" ABI використовувався в 2,95 і раніше, якщо я читаю їхні журнали змін.
[2] Не вдалося знайти жодного ресурсу, що перераховує std::type_info
стабільність об'єкта за платформою. Для компіляторів , я мав доступ до, я використовував наступне: echo "#include <typeinfo>" | gcc -E -dM -x c++ -c - | grep GXX_MERGED_TYPEINFO_NAMES
. Цей макрос керує поведінкою operator==
для std::type_info
STCC GCC, ніж GCC 3.0. Я виявив, що mingw32-gcc підкоряється Windows C ++ ABI, де std::type_info
об'єкти не унікальні для типу через DLL; typeid(a) == typeid(b)
дзвінки strcmp
під кришками. Я припускаю, що на однопрограмних вбудованих цілях, таких як AVR, де немає коду, з яким можна зв’язатись, std::type_info
об'єкти завжди стабільні.