c++中的单虚拟继承编译器优化

single virtual inheritance compiler optimization in c++?

本文关键字:继承 编译器 优化 虚拟 单虚拟 c++      更新时间:2023-10-16

如果我在C++项目中遇到这种情况:

  • 1个基类"base"仅包含纯虚拟函数
  • 1个类"Derived",这是唯一从"Base"继承(public)的类

编译器会生成VTABLE吗?

似乎没有必要,因为项目只包含一个Base*指针可能指向的类(Derived),所以在所有情况下,这都可以在编译时解决。

如果您想为单元测试进行依赖项注入,但又不想在生产代码中产生VTABLE查找成本,那么这很有趣。

我没有硬数据,但我有充分的理由说不,它不会把虚拟调用变成静态调用。

  • 通常,编译器只看到一个编译单元。它不知道只有一个子类,因为五个月后你可能会写另一个子类、编译它、从备份中获取一些古老的对象文件并将它们链接在一起
  • 虽然链接时间优化确实能看到全貌,但它们通常对程序的低级别表示起作用。例如,这种表示允许静态调用的内联,但不表示继承信息(可能作为可选元数据除外),并且已经明确说明了虚拟调用和vtables。我知道Clang就是这样,IIRC gcc的整个程序优化也适用于一些低级IR(GIMPLE?)
  • 还要注意,使用动态加载,在编译和LTO之后很长一段时间,您仍然可以添加更多的子类。你可能不需要它,但如果我是一名编译器作者,我会厌倦添加一个优化,让人们在非常具体、难以追踪的情况下完全中断虚拟调用
  • 这很少值得麻烦——如果你不需要虚拟调用(例如,因为你知道你不需要任何子类),就不要制作virtual。回顾您的设计。如果您需要一些多态性,但不需要虚拟的全部功能,那么奇怪的重复模板模式可能会有所帮助

编译器根本不必使用基于vtable的虚拟函数调度实现,因此问题的答案将特定于您正在使用的实现。

vtable通常不仅用于虚拟函数,而且在执行某些dynamic_cast或程序访问类的type_info时,它还用于识别类类型。

如果编译器检测到没有任何虚拟函数需要动态调度,并且没有使用任何其他功能,那么它可以删除vtable指针作为优化。

显然,编译器编写者认为不值得为此付出代价。可能是因为它不会经常使用。