プロファイラーは決して嘘をつきません。
私は 18 ~ 20 型の非常に安定した階層を持っているため、単純な列挙型メンバーを使用するだけでうまくいき、RTTI の「高い」コストを回避できるのではないかと考えました。if
私は、RTTI が実際にそれが導入する声明よりも高価であったかどうか懐疑的でした. 少年ああ、少年ですね。
RTTIは高価であり、同等のステートメントやC++ の単純なプリミティブ変数よりもはるかに高価であることが判明しました。したがって、S.Lott の回答は完全に正しいわけではありません。RTTI には追加のコストがかかります。これは、ステートメントが混在しているからというだけではありません。これは、RTTI が非常に高価であるためです。if
switch
if
このテストは、Apple LLVM 5.0 コンパイラで行われ、ストックの最適化が有効になっています (デフォルトのリリース モード設定)。
したがって、以下の 2 つの関数があり、それぞれが 1) RTTI または 2) 単純なスイッチを介してオブジェクトの具体的なタイプを把握します。それは 50,000,000 回行われます。これ以上苦労することなく、50,000,000 回の実行に対する相対ランタイムを提示します。

そうです、実行時間の94%dynamicCasts
がかかりました。ブロックは3.3%しかかかりませんでした。regularSwitch
enum
簡単に言うと、RTTI を実行する必要があり、パフォーマンスが最も重要な場合は、以下で行ったように 'd 型をフックするエネルギーがある場合は、おそらくそれをお勧めします。メンバーの設定は1 回だけで済み(必ずすべてのコンストラクターを介して取得してください)、その後は絶対に書き込まないでください。
とは言っても、これを行うことで OOP プラクティスが台無しになることはありません。これは、型情報が単に利用できず、RTTI の使用に追い詰められている場合にのみ使用することを意図しています。
#include <stdio.h>
#include <vector>
using namespace std;
enum AnimalClassTypeTag
{
TypeAnimal=1,
TypeCat=1<<2,TypeBigCat=1<<3,TypeDog=1<<4
} ;
struct Animal
{
int typeTag ;// really AnimalClassTypeTag, but it will complain at the |= if
// at the |='s if not int
Animal() {
typeTag=TypeAnimal; // start just base Animal.
// subclass ctors will |= in other types
}
virtual ~Animal(){}//make it polymorphic too
} ;
struct Cat : public Animal
{
Cat(){
typeTag|=TypeCat; //bitwise OR in the type
}
} ;
struct BigCat : public Cat
{
BigCat(){
typeTag|=TypeBigCat;
}
} ;
struct Dog : public Animal
{
Dog(){
typeTag|=TypeDog;
}
} ;
typedef unsigned long long ULONGLONG;
void dynamicCasts(vector<Animal*> &zoo, ULONGLONG tests)
{
ULONGLONG animals=0,cats=0,bigcats=0,dogs=0;
for( ULONGLONG i = 0 ; i < tests ; i++ )
{
for( Animal* an : zoo )
{
if( dynamic_cast<Dog*>( an ) )
dogs++;
else if( dynamic_cast<BigCat*>( an ) )
bigcats++;
else if( dynamic_cast<Cat*>( an ) )
cats++;
else //if( dynamic_cast<Animal*>( an ) )
animals++;
}
}
printf( "%lld animals, %lld cats, %lld bigcats, %lld dogs\n", animals,cats,bigcats,dogs ) ;
}
//*NOTE: I changed from switch to if/else if chain
void regularSwitch(vector<Animal*> &zoo, ULONGLONG tests)
{
ULONGLONG animals=0,cats=0,bigcats=0,dogs=0;
for( ULONGLONG i = 0 ; i < tests ; i++ )
{
for( Animal* an : zoo )
{
if( an->typeTag & TypeDog )
dogs++;
else if( an->typeTag & TypeBigCat )
bigcats++;
else if( an->typeTag & TypeCat )
cats++;
else
animals++;
}
}
printf( "%lld animals, %lld cats, %lld bigcats, %lld dogs\n", animals,cats,bigcats,dogs ) ;
}
int main(int argc, const char * argv[])
{
vector<Animal*> zoo ;
zoo.push_back( new Animal ) ;
zoo.push_back( new Cat ) ;
zoo.push_back( new BigCat ) ;
zoo.push_back( new Dog ) ;
ULONGLONG tests=50000000;
dynamicCasts( zoo, tests ) ;
regularSwitch( zoo, tests ) ;
}