Niezależnie od kompilatora, zawsze możesz zaoszczędzić na czasie wykonywania, jeśli możesz sobie na to pozwolić
if (typeid(a) == typeid(b)) {
B* ba = static_cast<B*>(&a);
etc;
}
zamiast
B* ba = dynamic_cast<B*>(&a);
if (ba) {
etc;
}
Pierwsza obejmuje tylko jedno porównanie std::type_info
; ta ostatnia wymaga koniecznie przejścia przez drzewo dziedziczenia oraz porównań.
Poza tym ... jak wszyscy mówią, wykorzystanie zasobów zależy od implementacji.
Zgadzam się z komentarzami wszystkich innych, że zgłaszający powinien unikać RTTI ze względów projektowych. Istnieje jednak są powody, aby skorzystać RTTI (głównie z powodu boost :: dowolnym). Mając to na uwadze, warto znać rzeczywiste wykorzystanie zasobów w typowych implementacjach.
Niedawno przeprowadziłem kilka badań nad RTTI w GCC.
tl; dr: RTTI w GCC zajmuje niewiele miejsca i typeid(a) == typeid(b)
jest bardzo szybki, na wielu platformach (Linux, BSD i być może platformy wbudowane, ale nie mingw32). Jeśli wiesz, że zawsze będziesz na błogosławionej platformie, RTTI jest bardzo blisko darmowego.
Ziarniste szczegóły:
GCC woli używać określonego "niezależnego od dostawcy" C ++ ABI [1] i zawsze używa tego ABI dla celów Linux i BSD [2]. W przypadku platform obsługujących ten interfejs ABI, a także słabe powiązanie, typeid()
zwraca spójny i niepowtarzalny obiekt dla każdego typu, nawet w przypadku granic dynamicznego łączenia. Możesz testować &typeid(a) == &typeid(b)
lub po prostu polegać na fakcie, że test przenośny typeid(a) == typeid(b)
faktycznie porównuje wewnętrznie wskaźnik.
W preferowanym ABI GCC klasa vtable zawsze zawiera wskaźnik do struktury RTTI dla danego typu, chociaż może nie być używana. Zatem typeid()
samo wywołanie powinno kosztować tyle samo, co każde inne wyszukiwanie w tabeli vtable (tak samo jak wywołanie wirtualnej funkcji składowej), a obsługa RTTI nie powinna wykorzystywać dodatkowej przestrzeni dla każdego obiektu.
Z tego, co widzę, struktury RTTI używane przez GCC (to wszystkie podklasy std::type_info
) mają tylko kilka bajtów dla każdego typu, poza nazwą. Nie jest dla mnie jasne, czy nazwy są obecne w kodzie wyjściowym nawet z -fno-rtti
. Tak czy inaczej, zmiana rozmiaru skompilowanego pliku binarnego powinna odzwierciedlać zmianę użycia pamięci w czasie wykonywania.
Szybki eksperyment (z użyciem GCC 4.4.3 na Ubuntu 10.04 64-bit) pokazuje, że w -fno-rtti
rzeczywistości zwiększa się rozmiar binarny prostego programu testowego o kilkaset bajtów. Dzieje się to konsekwentnie w przypadku kombinacji -g
i -O3
. Nie jestem pewien, dlaczego rozmiar miałby się zwiększyć; jedną z możliwości jest to, że kod STL GCC zachowuje się inaczej bez RTTI (ponieważ wyjątki nie będą działać).
[1] Znany jako Itanium C ++ ABI, udokumentowany pod adresem http://www.codesourcery.com/public/cxx-abi/abi.html . Nazwy są strasznie zagmatwane: nazwa odnosi się do oryginalnej architektury programistycznej, chociaż specyfikacja ABI działa na wielu architekturach, w tym i686 / x86_64. Komentarze w wewnętrznym źródle GCC i kodzie STL odnoszą się do Itanium jako „nowego” ABI w przeciwieństwie do „starego”, którego używali wcześniej. Co gorsza, „nowy” / Itanium ABI odnosi się do wszystkich wersji dostępnych za pośrednictwem -fabi-version
; „stary” ABI poprzedził tę wersję. GCC przyjęło Itanium / versioned / "nowy" ABI w wersji 3.0; "stary" ABI był używany w 2.95 i wcześniejszych, jeśli dobrze czytam ich dzienniki zmian.
[2] Nie mogłem znaleźć żadnego zasobu zawierającego listę std::type_info
stabilności obiektów według platformy. Dla kompilatorów miałem dostęp do użyłem co następuje: echo "#include <typeinfo>" | gcc -E -dM -x c++ -c - | grep GXX_MERGED_TYPEINFO_NAMES
. To makro kontroluje zachowanie operator==
for std::type_info
w STL GCC, począwszy od GCC 3.0. Zauważyłem, że mingw32-gcc jest zgodny z systemem Windows C ++ ABI, gdzie std::type_info
obiekty nie są unikalne dla typu w bibliotekach DLL; typeid(a) == typeid(b)
rozmowy strcmp
pod kołdrą. Spekuluję, że w przypadku celów osadzonych w jednym programie, takich jak AVR, gdzie nie ma kodu, z którym można by się połączyć, std::type_info
obiekty są zawsze stabilne.