'final'说明符是否会增加任何开销?

Lau*_*kas 8 c++ c++11 c++14

final在一个class或一个上使用说明符function添加任何内存或CPU开销,还是仅在编译时使用?

如何std::is_final识别什么是最终的?

Yak*_*ont 22

它实际上可以减少开销.在极少数情况下,增加它.

如果您有一个指向final类的指针,则可以对A任何虚拟方法调用进行反虚拟化并直接调用.类似地,可以对虚拟final方法的调用进行去虚拟化.此外,类的继承树final是固定的,即使它包含virtual父类,因此您可以对某些父访问进行去虚拟化.

这些去虚拟化中的每一个都减少或消除了查询运行时结构(vtable)的要求.

可能会有轻微的下行空间.某些编码技术依赖于vtable访问以避免直接访问符号,然后不导出符号.访问vtable可以通过约定来完成(没有来自库的符号,只是所讨论的类的头文件),而访问方法直接涉及链接该符号.

这打破了一种形式的动态C++库链接(在这种情况下,您可以避免链接多于dll加载符号和/或返回指针的C链接函数,并通过其vtable导出类).

如果您链接动态库中的符号,动态库符号加载也可能比vtable查找更昂贵.我没有经历或描述过这个,但我看到它声称.一般来说,收益应该超过这些成本.任何此类成本都是实施质量问题,因为该方法不会强制要求发生成本final.

最后,final禁止类上的空基优化技巧,其中有人知道你的类没有状态,并从中继承以减少将类的实例"存储"从1字节到0字节的开销.如果您的类为空并且不包含虚方法/继承,请不要使用final以避免被阻止.final功能没有等价物.

除了EBO优化问题(仅在空类型中出现),任何开销final都来自其他代码与其交互的方式,并且很少见.更常见的是,它会使其他代码更快,因为直接与方法交互可以更直接地调用方法,并且可以导致连锁优化(因为编译器可以更充分地理解调用).

将空类型除外的任何内容标记final为最终版本在运行时几乎肯定是无害的.在具有虚函数和继承的类上执行此操作可能在运行时很有用.


std::is_final类似的特征几乎都是通过编译器内置的魔法实现的.许多特征std需要这样的魔力.请参阅如何检测C++ 11中的类是否是最终的?(感谢@Csq的发现)