我有以下情况:
class A { public: A(int whichFoo); int foo1(); int foo2(); int foo3(); int callFoo(); // cals one of the foo's depending on the value of whichFoo };
在我当前的实现中,我保存whichFoo
构造函数中的数据成员的值,并使用switch
in callFoo()
来决定要调用哪个foo.或者,我可以switch
在构造函数中使用a 来保存指向fooN()
要调用的权限的指针callFoo()
.
我的问题是,如果A类的一个对象只构造一次,那么哪种方式更有效,而callFoo()
被称为非常多次.所以在第一种情况下我们有多个switch语句的执行,而在第二种情况下只有一个开关,并且使用指向它的指针多次调用成员函数.我知道使用指针调用成员函数比直接调用它要慢.有人知道这个开销是多少还是少于一个switch
?
澄清:我意识到你从来没有真正知道哪种方法可以提供更好的性能,直到你尝试并计时.但是,在这种情况下,我已经实施了方法1,并且我想知道方法2是否可以至少在原则上更有效.它似乎可以,现在我有理由去实现它并尝试它.
哦,我也喜欢方法2更好的审美原因.我想我正在寻找实现它的理由.:)
你是否确定通过指针调用成员函数比直接调用它更慢?你能衡量差异吗?
一般来说,在进行绩效评估时,不应该依赖自己的直觉.坐下来使用您的编译器和计时功能,并实际测量不同的选择.你可能会感到惊讶!
更多信息:有一篇优秀的文章成员函数指针和最快可能的C++代表,它们详细介绍了成员函数指针的实现.
你可以这样写:
class Foo { public: Foo() { calls[0] = &Foo::call0; calls[1] = &Foo::call1; calls[2] = &Foo::call2; calls[3] = &Foo::call3; } void call(int number, int arg) { assert(number < 4); (this->*(calls[number]))(arg); } void call0(int arg) { cout<<"call0("<实际函数指针的计算是线性和快速的:
(this->*(calls[number]))(arg); 004142E7 mov esi,esp 004142E9 mov eax,dword ptr [arg] 004142EC push eax 004142ED mov edx,dword ptr [number] 004142F0 mov eax,dword ptr [this] 004142F3 mov ecx,dword ptr [this] 004142F6 mov edx,dword ptr [eax+edx*4] 004142F9 call edx请注意,您甚至不必在构造函数中修复实际的函数编号.
我已将此代码与a生成的asm进行了比较
switch
.该switch
版本不提供任何性能提升.