c++ 性能 #
虚函数 #
大多数编译器采用虚函数表的实现,即对每一个包含虚函数的类生成一个虚函数表,一个指向虚函数表的指针被放在对象的首地址(不考虑多继承),虚函数表中存储该类所有的虚函数地址。当使用引用或者指针调用虚函数时,首先通过虚函数表指针找到虚函数表,然后通过偏移量找到虚函数地址并调用
空间开销 #
- 需要为每一个包含虚函数的类生成一个虚函数表
- 对于包含虚函数的类的实例,每个实例都包含一个虚函数表指针用于指向对应的虚函数表,所以每个实例的空间占用都增加一个指针大小
可能会造成缓存的不友好,在一定程度上影响程序性能
时间开销 #
增加一次内存寻址,通过虚函数表指针找到虚函数表,实际影响不大
背后开销 #
普通函数调用是一个直接调用,虚表调用时一次间接调用
直接调用的跳转地址是编译器确定的,间接调用是运行到该指令时从寄存器中取出地址然后跳转。
对于直接调用,不存在分支跳转,因为跳转地址是编译器确定的,cpu 直接去跳转地址去后面的指令即可,不存在分支预测,可以保证 cpu 流水线不被打断
对于间接寻址,由于跳转地址不确定,所以此处会有多个分支可能,需要分支预测器进行预测。如果分支预测失败,会导致流水线冲刷,重新进行取指,译码等操作,对程序性能有很大影响