好吧,探查器永远不会说谎。
由于我有一个非常稳定的18-20类型层次结构,并且变化不大,所以我想知道是否仅使用一个简单的枚举成员就能达到目的,并且避免了RTTI所谓的“高”成本。我怀疑RTTI是否实际上比if
它引入的陈述要昂贵。男孩,男孩,是。
事实证明,RTTI 是昂贵的,比C ++中的等效语句或简单的原始变量要昂贵得多。因此,S.Lott的回答并不完全正确,RTTI 会产生额外的成本,这也不是因为只是在声明中有所陈述。这是因为RTTI非常昂贵。if
switch
if
该测试是在Apple LLVM 5.0编译器上完成的,并启用了库存优化功能(默认发布模式设置)。
因此,我有以下2个功能,每个功能都可以通过1)RTTI或2)简单的开关来确定对象的具体类型。它这样做了50,000,000次。事不宜迟,我向您介绍了50,000,000次运行的相对运行时间。
没错,dynamicCasts
占用了94%的运行时间。而该regularSwitch
区块仅占3.3%。
长话短说:如果您有能力enum
像我在下文中介绍的那样插入'd类型,我可能会推荐它,如果您需要执行RTTI 并且性能至关重要。它只需要设置一次成员(确保通过所有构造函数获取它),并且一定不要在以后再编写它。
就是说,这样做不应该弄乱您的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 ) ;
}