C++动态分派无需虚函数表

7
据我所知,C++标准并不要求使用虚函数表(也称为vtable)实现动态分派。然而,我得到的印象是vtable是事实上的标准实现。我想知道是否有使用其他机制或至少允许使用其他机制的C++编译器。

不,因为vtable是最有效的方法。 - Alex
3
@Alex,高效是主观的。我同意在一般情况下,虚函数表可能是最平衡的解决方案,但它不是最快的,因此我可以很容易地想象出一种偏爱更快代码但较慢编译和更大映像的小众编译器。 - FireAphis
1
Andrei Alexandrescu谈到了一些关于实现自己的继承机制以优化某些体系结构上的函数指针查找的内容(它仍然是一个虚函数表,只是以特定方式组织):http://channel9.msdn.com/Events/GoingNative/2013/Writing-Quick-Code-in-Cpp-Quickly(您可以跳转到讲话的约32分钟处)。 - Michael
@kec,同意。我主要是在想可能有一些具有“技巧”的架构可以在没有虚表的情况下实现超级高效的动态分派,但通过谷歌搜索并没有找到相关信息。 - FireAphis
1
如果你认为“vtable...不是最快的”,那么你应该在问题中提出一个替代方案。加速调用的一种方法是去虚拟化,这是大多数现代C++编译器执行的优化(而且很容易通过谷歌搜索获得,提示,提示);我相信如果你启用LTO,使用clang和gcc会获得更好的结果。 - rici
显示剩余7条评论
1个回答

3
C++标准对虚函数和调用机制的实现没有太多限制。然而,它列出了许多不能被虚拟化的内容,这实际上增加了自由度。
从n3797 10.3/1:
虚函数支持动态绑定和面向对象编程。
然后是关于什么构成“覆盖”和“最终覆盖者”的大量内容。
从5.2.2/1:
否则[函数是虚拟的],在对象表达式的动态类型中调用其最终覆盖者(10.3);这样的调用称为虚函数调用。[注意:动态类型是当前对象表达式所引用的对象的类型……]
因此,C++标准定义了一种基于对象的动态分派的受限形式,除此之外没有太多限制。只要每个对象都携带一个可以调用任何虚函数的机制,其他所有内容都可以随意更改。
是的,虚函数表很常见,但并不是最后的选择。它们是一个重要的内存和速度成本,特别是对于多重继承。我可以轻松想出一种不使用虚函数表但同样快速且使用更少对象内存的机制,但需要更多的代码或静态内存空间。各种研究人员已经设计出了大量的技术,甚至有些已经被专利化。有些技术提供更好的类型安全性,或更好的分支预测,甚至更快的查找。我不认为提供链接有太多意义——您也可以轻松找到它们。
但是,我不知道是否有任何生产C++编译器使用这些机制。也许现在是时候考虑一种了?

2
这里有一篇来自 Stroustrup 本人的论文,其中他给出了一个更快的 dynamic cast 实现的例子。然而,我不清楚他希望如何扩展它以支持 DLL(参见 DYNAMICALLY LOADED CLASSES),而我看到的大多数替代方案都存在这个问题:没有动态加载代码时一切都很容易。 - Matthieu M.
@MatthieuM.:所以可以假设编译器可以实现更快的机制,只要它提供了回退到始终有效的东西,并掩盖了差异。编译器编写者的生活并没有变得更简单,是吗? - david.pfx

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接