我有一些代码具有这样的结构:
({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
中将其设置为最终帮助吗?
在这样的循环中调用相同的虚拟函数是否存在虚拟函数的所有性能问题?
答案 0 :(得分:2)
评论对为什么这可能是过早的优化提出了一些好的建议,但是可以直接回答您的问题:
是否有一种以非虚拟方式调用doStuff()的方式,因此没有开销?
如果您有一组固定的类型,则可以通过带标签的联合,例如std::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;
/*...*/
}
在这样的循环中调用相同的虚拟函数是否存在虚拟函数的所有性能问题?
现代处理器非常擅长间接分支预测,因此您可能不会在循环中调用虚拟方法时看到太多开销。