C++内联函数

来由

使用内联函数代替宏提高效率,因为宏容易出错。

inline只是对编译器的一个建议,不是强制命令,编译器可能接受也可能忽略。

1、inline的优缺点

优点:

  • 免除函数调用的开销,类似宏一样提高效率,但比宏安全;
  • 可以享受编译器语境的优化(一般编译器不会对outlined函数调用执行最优化 )。

缺点:

  • 以函数本体代替函数调用,可能造成代码膨胀,膨胀太大的话可能会造成额外的换页行为,降低指令高速缓存装置的集中率,以及伴随效率的损失;
  • 不利于调试;
  • 如果日后该函数被改变,则所有用到该函数的客户端程序都必须重新编译;而如果f不是inline函数,客户端只需重新链接,如果是动态链接,甚至不需要管。

2、隐式内联、显式内联

  • 隐式内联:
    当函数定义在类的内部时(包括友元函数),这个函数是隐式inline的(隐式内联只有这一种情况,构造、析构、虚函数除外)。

    class Person {
    public:
        //隐式内联(编译器自动申请),这个函数不仅在类中声明,还在类中进行了定义
        int age()const { return theAge; }
    private:
        int theAge;
    };
    

    构造函数与析构函数除外,因为一般编译器会在其中添加很多隐藏代码。虚函数在运行期确定,因此也不内联。

  • 显式内联:
    我们也可以通过inline关键字显式的指出一个函数作为内联函数。例如:

    template<typename T>
    inline const T& std::max(const T& a, const T& b)
    {
        return a < b ? b : a;
    }
    

注意:inline函数的定义通常被置于头文件内,因为大多数建置环境在编译过程中进行inlining,需要知道内联函数长什么样子。inlining在大多数C++程序中是编译期的行为(但是也有少数情况是在运行期链接期完成inlining)。但如果多个文件调用该头文件,且同时编译器拒绝内联,则有可能出现多重定义,此时内联函数需要加static修饰,不过高级编译器可能不会报错。

3、编译器拒绝内联的情况

即使你将函数声明为inline的,但是在有些情况下编译器会拒绝将函数作为inlining。例如:

  • 太过复杂的函数:例如带有循环或递归,因为函数调用的消耗比起循环和递归太小;
  • 对virtual函数的调用(除非是最平淡无奇的):因为virtual意为“等待”,直到运行期才确定调用哪个函数,而inline意味着在编译期就能够确定调用函数本体。因此virtual函数将被编译器拒接生成为inline的。
  • 需要显式或隐式地取函数地址(存放函数代码)时,编译器必须为函数代码分配内存地址。

注意:g++是否内联可能和编译选项中的优化等级相关:不优化时不进行内联,开优化才内联。

4、总结

将大多数inlining限制在小型、被频繁调用的函数身上。这可使潜在的代码膨胀问题最小化,使程序的速度提升机会最大化。

参考:
《C++编程思想卷1》第九章内联函数
《Effective C++》条款30

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值