c – 从另一个虚拟函数调用时的内联虚函数?
作者:互联网
我有一个包含两个虚拟成员函数的类:foo和wrapper. foo简短而快速,包装器包含一个多次调用foo的循环.我希望有一些方法可以在包装器函数内部调用foo,即使是从指向对象的指针调用时:
MyClass *obj = getObject();
obj->foo(); // As I understand it, this cannot be inlined. That's okay.
obj->wrapper(); // Nor will this. However, I hope that the machine code
// for the wrapper function will contain inlined calls to
// foo().
本质上,我希望编译器生成包装函数的多个版本 – 每个可能的类一个 – 以及对适当的foo的内联调用,这应该是可能的,因为在选择要执行的包装函数之前确定了对象类型.这可能吗?任何编译器都支持这种优化吗?
编辑:到目前为止,我很感谢所有的反馈和答案,我最终可能会选择其中一个.但是,大多数回复都忽略了我的问题的最后部分,在那里我解释了为什么我认为这种优化应该是可行的.这真的是我的问题的关键,我仍然希望有人可以解决这个问题.
编辑2:我选择弗拉德的答案,因为他都提出了流行的解决方法,并部分解决了我提出的优化问题(在大卫答案的评论中).感谢所有写过答案的人 – 我把它们都读了,并没有一个明确的“赢家”.
此外,我发现了一篇学术论文,提出了与我的建议非常相似的优化:http://www.ebb.org/bkuhn/articles/cpp-opt.pdf.
解决方法:
在某些情况下,编译器可以在编译时确定虚拟调度行为并执行非虚函数调用甚至内联函数.只有当它能够确定你的类是继承链中的“顶层”或者这两个函数没有超载时,它才能做到这一点.通常,这根本不可能,特别是如果您没有为整个程序启用延迟时间优化.
除非您想检查编译器优化的结果,否则最好不要在内部循环中使用虚函数.例如,像这样:
class Foo {
public:
virtual void foo()
{
foo_impl();
}
virtual void bar()
{
for (int i = 0; i < ∞; ++i) {
foo_impl();
}
}
private:
void foo_impl() { /* do some nasty stuff here */ }
};
但在这种情况下,你明确地放弃了某个人可能会进来的想法,从你的班级继承并投入他们自己的“foo”实现,由你的“酒吧”调用.他们基本上需要重新实施两者.
另一方面,它闻起来有点像过早的优化.现代CPU很可能会“锁定”您的循环,预测它的退出并反复执行相同的μOP,即使您的方法实际上是虚拟的.因此,我建议您在花时间优化它之前仔细确定这是一个瓶颈.
标签:c,inline,gcc,virtual-functions 来源: https://codeday.me/bug/20190725/1537046.html