面试题答案
一键面试性能开销主要体现方面
- 空间开销:每个包含虚函数的类对象都需要额外存储一个指向虚函数表(vtable)的指针(vptr),这会增加对象的内存占用。尤其在大型项目中,大量对象的存在会导致可观的额外内存消耗。
- 时间开销 - 函数调用:虚函数调用需要通过对象的vptr找到对应的vtable,然后在vtable中查找目标函数的地址,最后才能调用函数。相比直接函数调用,多了间接寻址的过程,增加了指令执行的数量和时间。
- 时间开销 - 动态链接:在运行时进行动态绑定,程序需要额外的逻辑来确定实际调用的函数,这涉及到运行时类型信息(RTTI)的获取和处理,增加了运行时的计算量。
优化方案及适用场景
- 使用静态多态(模板)
- 适用场景:当行为的变化在编译期就可以确定时适用。例如,不同类型的数学计算操作,针对不同数据类型(如int、float等)的加法操作,模板可以在编译期为每种数据类型生成专门的函数实例,避免运行时的动态绑定开销。在库开发中,如STL容器和算法的实现,广泛使用模板来提供高效的通用功能。
- 减少虚函数层级深度
- 适用场景:在类继承体系复杂,虚函数层级较深的情况下适用。例如,在一个多层继承的图形绘制类体系中,如果存在过多层的虚函数重写,将虚函数尽量集中在少数几层,可以减少每次虚函数调用时在虚函数表中查找的深度,从而提高性能。
- 缓存虚函数调用结果
- 适用场景:对于一些频繁调用且结果相对稳定的虚函数,如一些与对象状态相关但状态变化不频繁的计算函数。例如,一个游戏角色类中有一个虚函数用于计算角色的战斗力,当角色的装备等影响战斗力的因素不频繁变化时,可以缓存该虚函数的计算结果,避免每次调用都进行动态绑定和计算。