c++中的单虚拟继承编译器优化
single virtual inheritance compiler optimization in c++?
如果我在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指针作为优化。
显然,编译器编写者认为不值得为此付出代价。可能是因为它不会经常使用。
相关文章:
- 尝试使用继承和模板实现CRTP.Visual Studio正在生成编译器错误
- 相对于继承的构造函数,gcc 编译器是否还有一个错误?
- 可变参数类模板和继承 - 默认编译器生成的构造函数
- 在此示例中,为什么视觉工作室编译器允许违反私人继承
- 包装结构的大小和带有不同编译器的继承
- 在多个继承的情况下,C 编译器如何处理成员变量内存偏移
- 在编译器中实现受保护/私有继承
- 编译器无法编译继承 C++
- 可以用参数包编译C 17 lambda继承的编译器
- 从 std::streambif 继承时不兼容析构函数编译器警告
- 使用继承的编译器错误lnk2019和c4930
- 编译器如何实现继承
- C 多重继承 - 编译器修改我的指针
- 编译器如何在继承C++中进行组合
- c++编译器错误中的简单类继承
- 类继承:编译器无法识别类的构造函数和成员函数
- 在多继承编译器的情况下访问成员变量是否依赖?如何正确地做
- 模板类、继承和指向成员函数的指针的编译器错误
- 在基类构造函数中使用参数时C++继承编译器错误
- c++中的单虚拟继承编译器优化