Независимо от компилятора, вы всегда можете сэкономить на времени выполнения, если можете себе позволить
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 (так же, как вызов виртуальной функции-члена), а поддержка 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 / versioned / "новый" 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
в GCC STL, начиная с GCC 3.0. Я обнаружил, что mingw32-gcc подчиняется Windows C ++ ABI, где std::type_info
объекты не уникальны для типа в библиотеках DLL; typeid(a) == typeid(b)
звонит strcmp
под одеяло. Я предполагаю, что в однопрограммных встроенных целях, таких как AVR, где нет кода для связывания, std::type_info
объекты всегда стабильны.
person
sbrudenell
schedule
02.12.2010
dynamic_cast
в C ++, и теперь в 9 из 10 раз, когда я нарушаю программу с помощью отладчика, она ломается внутри внутренней функции динамического приведения. Это чертовски медленно. - person user541686   schedule 10.09.2012