在循环中调用同一虚函数的开销



我有一些代码的结构是这样的:

(doStuff2()将通过Class1指针调用。这将循环调用doStuff()。有多个类,例如Class3因此Class2将有多个模板实例。

struct Class1{
virtual void doStuff2() = 0;
};
template<typename T> struct Class2 : public Class1{
virtual void doStuff() { /*code*/};
void doStuff2() override {
// Call this in a huge loop.
doStuff();
}
};
struct Class3 : public Class2<SomeType>{
void doStuff() override final { /*code*/};
};
//...
void someFunc(Class1 *p_class1){
p_class1->doStuff2();
}

我的问题:有没有办法以非虚拟的方式调用doStuff(),这样就不会产生开销?让它在Class2中成为纯虚拟,在Class3中成为最终的,会有所帮助吗?

在这样的循环中调用同一个虚函数是否具有虚函数的所有性能问题?

这些评论对为什么这可能是过早的优化有一些很好的建议,但要直接回答您的问题:

有没有办法以非虚拟的方式调用doStuff((,这样就不会有开销?

如果你有一组固定的类型,那么你可以通过标记的联合来运行时调度非虚拟方法,alastd::variant

using Class1 = std::variant<Class2<SomeType1>, Class2<SomeType2>>;
/*...*/
std::visit([](auto&& c) { c.doStuff(); }, p_class1);

这大致优化为一些好的 C 式切换:

switch (p_class1.class_type) {
case CLASS2_SOMETYPE1:
((Class2<SomeType1>)p_class1).doStuff();
break;
/*...*/
}

在这样的循环中调用同一个虚函数是否具有虚函数的所有性能问题?

现代处理器非常擅长间接分支预测,因此您可能不会看到在循环中调用虚拟方法的开销。

最新更新