Derleyiciden bağımsız olarak, bunu karşılayabiliyorsanız her zaman çalışma zamanında tasarruf edebilirsiniz
if (typeid(a) == typeid(b)) {
B* ba = static_cast<B*>(&a);
etc;
}
onun yerine
B* ba = dynamic_cast<B*>(&a);
if (ba) {
etc;
}
İlki sadece bir karşılaştırmayı içerir std::type_info
; ikincisi zorunlu olarak bir miras ağacının ve karşılaştırmaları geçmeyi içerir.
Geçmişte ... herkesin dediği gibi, kaynak kullanımı uygulamaya özeldir.
Gönderenin tasarım nedenleriyle RTTI'dan kaçınması gerektiğini herkesin yorumlarına katılıyorum. Bununla birlikte, RTTI kullanmak için iyi nedenler vardır (esas olarak boost :: any nedeniyle). Bunu akılda tutarak, ortak uygulamalarda gerçek kaynak kullanımını bilmek yararlıdır.
Geçenlerde GCC'de RTTI ile ilgili bir sürü araştırma yaptım.
tl; dr: GCC'deki RTTI typeid(a) == typeid(b)
, birçok platformda (Linux, BSD ve belki de gömülü platformlar, ancak mingw32 değil) ihmal edilebilir alan kullanır ve çok hızlıdır. Her zaman kutsanmış bir platformda olacağınızı biliyorsanız, RTTI ücretsizdir.
Cesur ayrıntılar:
GCC belirli bir "satıcıdan bağımsız" C ++ ABI [1] kullanmayı tercih eder ve bu ABI'yi her zaman Linux ve BSD hedefleri için kullanır [2]. Bu ABI'yi ve aynı zamanda zayıf bağlantıyı destekleyen platformlar typeid()
için, dinamik bağlantı sınırları dahilinde bile her tür için tutarlı ve benzersiz bir nesne döndürür. Test edebilir &typeid(a) == &typeid(b)
veya taşınabilir testin typeid(a) == typeid(b)
aslında sadece bir işaretçiyi dahili olarak karşılaştırdığına güvenebilirsiniz .
GCC'nin tercih edilen ABI'sinde, bir sınıf vtable her zaman tür başına RTTI yapısına bir işaretçi tutar, ancak kullanılmayabilir. Bir Böylece typeid()
çağrı kendisi olmalıdır yalnızca başka vtable arama (sanal üye işlevini çağırarak aynı) kadar mal ve RTTI destek olmamalıdır her nesne için herhangi bir ekstra boşluk kullanın.
Yapabileceğimden, GCC tarafından kullanılan RTTI yapıları (bunların tüm alt sınıfları std::type_info
), adın yanı sıra, her tür için sadece birkaç bayt tutar. İsimlerin çıktı kodunda bile bulunup bulunmadığı net değil -fno-rtti
. Her iki durumda da, derlenmiş ikilinin boyutundaki değişiklik, çalışma zamanı bellek kullanımındaki değişikliği yansıtmalıdır.
Hızlı bir deneme (Ubuntu 10.04 64 bit üzerinde GCC 4.4.3 kullanarak), basit bir test programının ikili boyutunu -fno-rtti
aslında birkaç yüz bayt artırdığını göstermektedir . Bu sürekli -g
ve ve kombinasyonları arasında gerçekleşir -O3
. Boyutun neden artacağından emin değilim; bir olasılık, GCC'nin STL kodunun RTTI olmadan farklı davranmasıdır (istisnalar çalışmadığından).
[1] http://www.codesourcery.com/public/cxx-abi/abi.html adresinde belgelenen Itanium C ++ ABI olarak bilinir . İsimler korkunç derecede kafa karıştırıcı: isim orijinal geliştirme mimarisine atıfta bulunsa da, ABI belirtimi i686 / x86_64 dahil birçok mimaride çalışıyor. GCC'nin iç kaynağındaki ve STL kodundaki yorumlar, Itanium'a daha önce kullandıkları "eski" ifadenin aksine "yeni" ABI olarak atıfta bulunur. Daha da kötüsü, "yeni" / Itanium ABI, mevcut tüm sürümleri ifade eder -fabi-version
; "eski" ABI bu sürümün önüne geçti. GCC, 3.0 sürümünde Itanium / versioned / "new" ABI'yi kabul etti; "eski" ABI 2.95 ve önceki sürümlerde kullanıldı.
[2] std::type_info
Platforma göre herhangi bir kaynak listeleme nesnesi kararlılığı bulamadım . Derleyici için ben aşağıdakileri kullanılan erişimi vardı: echo "#include <typeinfo>" | gcc -E -dM -x c++ -c - | grep GXX_MERGED_TYPEINFO_NAMES
. Bu makro kontroller davranışı operator==
için std::type_info
GCC 3.0 itibariyle GCC en STL. Mingw32-gcc, std::type_info
nesnelerin DLL'lerde bir tür için benzersiz olmadığı Windows C ++ ABI, itaat ettiğini buldum ; örtü altında typeid(a) == typeid(b)
çağırır strcmp
. Bağlanacak bir kodun olmadığı AVR gibi tek programlı gömülü hedeflerde, std::type_info
nesnelerin her zaman kararlı olduğunu tahmin ediyorum .