前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >秒杀面试题:深入final,掌握C++性能优化

秒杀面试题:深入final,掌握C++性能优化

作者头像
公众号guangcity
发布2024-01-11 13:41:27
2140
发布2024-01-11 13:41:27
举报
文章被收录于专栏:光城(guangcity)光城(guangcity)

秒杀面试题:深入final,掌握C++性能优

C++11之后有了final,它用来指定不能在派生类中重写虚函数,或者不能从中派生类。

例如下面这个例子,当添加final之后:

  • foo函数被禁止重写
  • bar函数被禁止重写
  • B类被禁止继承

那么,除了这些还有什么?如果面试官问你final,你只答这些能过?接下来本文来拓展一下final的妙用!

代码语言:javascript
复制
struct Base
{
    virtual void foo();
};
 
struct A : Base
{
    void foo() final; // Base::foo is overridden and A::foo is the final override
    void bar() final; // Error: bar cannot be final as it is non-virtual
};
 
struct B final : A // struct B is final
{
    void foo() override; // Error: foo cannot be overridden as it is final in A
};
struct C : B {}; // Error: B is final

虚函数需要在运行时通过vtable进行间接调用,其中会发生分支预测和指令缓存,还会影响内联。因此相比于函数的直接调用,其性能较差。

通过final可以做到去虚拟化,它是一种编译器优化手段,尝试在编译时而非运行时解决函数调用问题。由于在编译时可以确定调用哪个函数,因此便不会存在前面的vtable问题了,从而极大的提升虚函数调用的性能。

1.去虚拟化与原生对比

以下面为例:A有两个接口,f1、f2,子类B继承A重写了这两个接口,f1后面添加了final,f2不变,f1与f2函数各自调用b的f1与f2。

代码语言:javascript
复制
class A {
public:
    virtual void f1() = 0;
    virtual void f2() = 0;
};

class B : public A {
public:
    void f1() final override {}
    void f2() override {}
};

void f1(B& b) {
    b.f1();
}

void f2(B &b) {
    b.f2();
}

其汇编代码如下:

https://gcc.godbolt.org/z/GT78G7T9z

代码语言:javascript
复制
B::f2():
        rep ret
f1(B&):
        rep ret
f2(B&):
        mov     rax, QWORD PTR [rdi]
        mov     rax, QWORD PTR [rax+8]
        cmp     rax, OFFSET FLAT:B::f2()
        jne     .L6
        rep ret
.L6:
        jmp     rax

从上面可以看到,对于f1(b)来说由于添加了final,我们可以看到直接调用了B的f1,而并没有加载B的vtable。对于f2(b)来说加载了B的vtable、比较虚函数地址,判断是否jmp。

上面这个例子比较简单,指针加载和跳转的成本可能看起来并不多,因为它只是几条指令,但是这可能涉及分支预测错误和缓存未命中问题,这可能会引发性能下降。

2.总结一下final

final在日常面试/工作中还是比较有用,如果面试官问你final,你可以解答如下。

  • 禁止继承
  • 禁止虚函数重写
  • 去虚拟化提升性能
  • 设计约束,禁止子类继承,放置子类重写

总的来说,final 关键字在 C++ 中用于阻止继承和虚函数重写,提高代码的性能、可维护性和安全性。使用 final 能够更加明确地表达代码的意图,并防止一些潜在的错误。


本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2024-01-10,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 光城 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 秒杀面试题:深入final,掌握C++性能优
    • 1.去虚拟化与原生对比
      • 2.总结一下final
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档