ผู้สร้างโปรไฟล์ไม่เคยโกหก
เนื่องจากฉันมีลำดับชั้นที่ค่อนข้างคงที่ของ 18-20 ประเภทที่ไม่เปลี่ยนแปลงมากนักฉันสงสัยว่าถ้าเพียงใช้สมาชิก enum ที่เรียบง่ายจะทำการหลอกลวงและหลีกเลี่ยงต้นทุน RTTI โดยอ้างว่า "สูง" ฉันสงสัยถ้า RTTI มีราคาแพงกว่าif
ข้อความที่แนะนำ บอยโอ้เด็กชายมันคือ
แต่กลับกลายเป็นว่า RTTI เป็นราคาแพงมากขึ้นมีราคาแพงกว่าเทียบเท่าif
คำสั่งหรือง่ายswitch
ในตัวแปรดั้งเดิมใน C ++ ดังนั้นคำตอบของ S.Lott ไม่ถูกต้องสมบูรณ์มีเป็นค่าใช้จ่ายเพิ่มเติมสำหรับ RTTI และก็ไม่ได้เนื่องจากเป็นเพียงแค่การมีif
คำสั่งในการผสม เป็นเพราะ RTTI นั้นมีราคาแพงมาก
การทดสอบนี้ทำกับคอมไพเลอร์ Apple LLVM 5.0 โดยเปิดการปรับแต่งสต็อกไว้ (การตั้งค่าโหมดรีลีสเริ่มต้น)
ดังนั้นฉันจึงมีฟังก์ชั่นด้านล่าง 2 ฟังก์ชันซึ่งแต่ละประเภทจะคำนวณประเภทวัตถุที่เป็นรูปธรรมไม่ว่าจะผ่าน 1) RTTI หรือ 2) สวิตช์ที่เรียบง่าย มันทำได้ 50,000,000 ครั้ง โดยไม่มีความกังวลใจเพิ่มเติมฉันนำเสนอ runtimes สัมพัทธ์สำหรับ 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 ) ;
}