问题描述
由于虚函数调用需要对v表进行额外的索引引用,因此虚函数调用的速度可能会很慢,这可能导致数据高速缓存未命中以及指令高速缓存未命中……不适用于对性能至关重要的应用程序. /p>
因此,我一直在思考一种克服虚拟功能性能问题的方法,但仍具有虚拟功能所提供的某些相同功能.
我相信以前已经做过,但是我设计了一个简单的测试,该测试允许基类存储可由任何派生类设置的成员函数指针.当我在任何派生类上调用Foo()时,它将调用适当的成员函数,而不必遍历v表...
我只是想知道这种方法是否可以替代虚拟呼叫范例,如果可以,为什么它不那么普遍?
提前感谢您的宝贵时间! :)
class BaseClass
{
protected:
// member function pointer
typedef void(BaseClass::*FooMemFuncPtr)();
FooMemFuncPtr m_memfn_ptr_Foo;
void FooBaseClass()
{
printf("FooBaseClass() \n");
}
public:
BaseClass()
{
m_memfn_ptr_Foo = &BaseClass::FooBaseClass;
}
void Foo()
{
((*this).*m_memfn_ptr_Foo)();
}
};
class DerivedClass : public BaseClass
{
protected:
void FooDeriveddClass()
{
printf("FooDeriveddClass() \n");
}
public:
DerivedClass() : BaseClass()
{
m_memfn_ptr_Foo = (FooMemFuncPtr)&DerivedClass::FooDeriveddClass;
}
};
int main(int argc, _TCHAR* argv[])
{
DerivedClass derived_inst;
derived_inst.Foo(); // "FooDeriveddClass()"
BaseClass base_inst;
base_inst.Foo(); // "FooBaseClass()"
BaseClass * derived_heap_inst = new DerivedClass;
derived_heap_inst->Foo();
return 0;
}
我做了一个测试,使用虚拟函数调用的版本在经过优化的系统上更快.
$ time ./main 1
Using member pointer
real 0m3.343s
user 0m3.340s
sys 0m0.002s
$ time ./main 2
Using virtual function call
real 0m2.227s
user 0m2.219s
sys 0m0.006s
这是代码:
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <stdio.h>
struct BaseClass
{
typedef void(BaseClass::*FooMemFuncPtr)();
FooMemFuncPtr m_memfn_ptr_Foo;
void FooBaseClass() { }
BaseClass()
{
m_memfn_ptr_Foo = &BaseClass::FooBaseClass;
}
void Foo()
{
((*this).*m_memfn_ptr_Foo)();
}
};
struct DerivedClass : public BaseClass
{
void FooDerivedClass() { }
DerivedClass() : BaseClass()
{
m_memfn_ptr_Foo = (FooMemFuncPtr)&DerivedClass::FooDerivedClass;
}
};
struct VBaseClass {
virtual void Foo() = 0;
};
struct VDerivedClass : VBaseClass {
virtual void Foo() { }
};
static const size_t count = 1000000000;
static void f1(BaseClass* bp)
{
for (size_t i=0; i!=count; ++i) {
bp->Foo();
}
}
static void f2(VBaseClass* bp)
{
for (size_t i=0; i!=count; ++i) {
bp->Foo();
}
}
int main(int argc, char** argv)
{
int test = atoi(argv[1]);
switch (test) {
case 1:
{
std::cerr << "Using member pointer\n";
DerivedClass d;
f1(&d);
break;
}
case 2:
{
std::cerr << "Using virtual function call\n";
VDerivedClass d;
f2(&d);
break;
}
}
return 0;
}
编译使用:
g++ -O2 main.cpp -o main
使用g ++ 4.7.2.
Virtual function calls can be slow due to virtual calls requiring an extra indexed deference to the v-table, which can result in a data cache miss as well as an instruction cache miss... Not good for performance critical applications.
So I have been thinking of a way to overcome this performance issue of virtual functions yet still having some of the same functionality that virtual functions provide.
I am confident that this has been done before, but I devised a simple test that allows the base class to store a member function pointer that can be set by any the derived class. And when I call Foo() on any derived class, it will call the appropriate member function without having to traverse the v-table...
I am just wondering if this method is a viable replacement for the virtual-call paradigm, if so, why is it not more ubiquitous?
Thanks in advance for your time! :)
class BaseClass
{
protected:
// member function pointer
typedef void(BaseClass::*FooMemFuncPtr)();
FooMemFuncPtr m_memfn_ptr_Foo;
void FooBaseClass()
{
printf("FooBaseClass() \n");
}
public:
BaseClass()
{
m_memfn_ptr_Foo = &BaseClass::FooBaseClass;
}
void Foo()
{
((*this).*m_memfn_ptr_Foo)();
}
};
class DerivedClass : public BaseClass
{
protected:
void FooDeriveddClass()
{
printf("FooDeriveddClass() \n");
}
public:
DerivedClass() : BaseClass()
{
m_memfn_ptr_Foo = (FooMemFuncPtr)&DerivedClass::FooDeriveddClass;
}
};
int main(int argc, _TCHAR* argv[])
{
DerivedClass derived_inst;
derived_inst.Foo(); // "FooDeriveddClass()"
BaseClass base_inst;
base_inst.Foo(); // "FooBaseClass()"
BaseClass * derived_heap_inst = new DerivedClass;
derived_heap_inst->Foo();
return 0;
}
I did a test, and the version using virtual function calls was faster on my system with optimization.
$ time ./main 1
Using member pointer
real 0m3.343s
user 0m3.340s
sys 0m0.002s
$ time ./main 2
Using virtual function call
real 0m2.227s
user 0m2.219s
sys 0m0.006s
Here is the code:
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <stdio.h>
struct BaseClass
{
typedef void(BaseClass::*FooMemFuncPtr)();
FooMemFuncPtr m_memfn_ptr_Foo;
void FooBaseClass() { }
BaseClass()
{
m_memfn_ptr_Foo = &BaseClass::FooBaseClass;
}
void Foo()
{
((*this).*m_memfn_ptr_Foo)();
}
};
struct DerivedClass : public BaseClass
{
void FooDerivedClass() { }
DerivedClass() : BaseClass()
{
m_memfn_ptr_Foo = (FooMemFuncPtr)&DerivedClass::FooDerivedClass;
}
};
struct VBaseClass {
virtual void Foo() = 0;
};
struct VDerivedClass : VBaseClass {
virtual void Foo() { }
};
static const size_t count = 1000000000;
static void f1(BaseClass* bp)
{
for (size_t i=0; i!=count; ++i) {
bp->Foo();
}
}
static void f2(VBaseClass* bp)
{
for (size_t i=0; i!=count; ++i) {
bp->Foo();
}
}
int main(int argc, char** argv)
{
int test = atoi(argv[1]);
switch (test) {
case 1:
{
std::cerr << "Using member pointer\n";
DerivedClass d;
f1(&d);
break;
}
case 2:
{
std::cerr << "Using virtual function call\n";
VDerivedClass d;
f2(&d);
break;
}
}
return 0;
}
Compiled using:
g++ -O2 main.cpp -o main
with g++ 4.7.2.
这篇关于C ++虚拟函数与成员函数指针(性能比较)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!