EffectiveC++-条款30:透彻了解 inlining 的里里外外

一. 内容

  1. inline 函数,多棒的点子!它们看起来像函数,动作像函数,比宏好用的多,见条款2,可以调用它们又不需花费因调用函数带来的额外开销。而且编译器最优化机制通常被设计来优化那些不含函数调用的代码,这意味编译器有能力对 inline 函数做语境相关的最优化
  2. 然后编写程序就像现实生活一样,没有白吃的午餐,inline函数也不例外。inline 函数背后的机制是:将对此函数的每一个调用都用函数本体替换之。这样无疑会增加产出码的大小,在一台内存有限的机器上,过度热衷 inline 机制会造成程序体积太大,即使拥有虚内存,inline 造成的代码膨胀亦会导致额外的换页行为,降低指令高速缓存装置的击中率,也就是cache miss,以及伴随而来的效率损失。反之,如果函数本身足够小,其 inline 产出的代码比函数调用产出的代码要少,那么将函数声明为 inline 确实会提高运行效率。
  3. 记住,inline 只是对编译器的一个申请,不是强制命令。这项申请可以隐式提出,也可以明确提出。隐式方式是将函数定义在 class 声明式内,这样的函数通常是成员函数,明确方式是在函数定义式前加上关键字 inline。示例如下:
    class Inline {
    public:
        Inline(int mNumber): Number(mNumber) {}
    public:
        void SetNumber(int mNumber) {
            Number = mNumber;
        }
    
        int GetNumber() const {
            return Number;
        }
    
    private:
        int Number;
    };
    
    inline void Try() {
        const Inline Inline(999);
        std::cout << Inline.GetNumber() << "\n";
    }
    
    其中 SetNumber,GetNumber 函数为隐式 inline,Try 函数为显式 inline。
  4. inline 函数通常一定被置于头文件。因为大多数构建环境在编译过程中进行 inlining,而为了将一个函数调用替换为被调用函数的本体,编译器必须知道那个函数长什么样子。只有少数某些构建环境可以在连接期完成,但毕竟是例外。inline 在大多数C++程序是编译期行为
  5. template 通常也被置于头文件内,因为它一旦被使用,编译器为了将它具现化,需要知道它长什么样子。只有少数在连接期完成。template 在大多数C++程序也是编译期行为
  6. 但 template 和 inline 是独立的,它们的具现化彼此无关,请根据自己的需要声明为 inline,避免 inline 不必要的成本。
  7. inline 只是申请,不是强制要求。对于那些过于复杂,如带有循环,递归的函数,编译器都会拒绝 inline,而对于就算最简单的 virtual 函数,编译器也拒绝 inline,这是很正常的,因为 virtual 需要等到运行期才能确定调用哪个函数,所以编译器无法在编译期获得 virtual 函数的本体用于替换调用行为,于是拒绝 inline。
  8. 这些叙述综合起来的意思是:一个表面上看似 inline 的函数 是否真的为 inline 取决于你的构建环境,取决于编译器。幸运的是,编译器将会对于那些你要求 inline 却 无法 inline 的函数提供警告信息,用于诊断。
  9. 但是有时候编译器虽然有意愿 inline 某个函数,但还是可能为该函数生成一个函数本体。举个例子,如果程序要取某个 inline 函数的地址,编译器通常必须为此函数生成一个 outlined 函数本体。毕竟编译器没有能力提出一个指针指向一个并不存在的函数。与此并提的是:编译器通常不对通过函数指针而进行的调用实施 inline。这意味着对 inline 函数的不同调用方式也决定了实际是否 inline。
  10. 但是即使你从未使用函数指针,编译器仍然可能不会 inline 一些函数,因为程序员不是唯一要求函数指针的人,有时候编译器会生成构造函数和析构函数的 outlined 副本,用于获得它们的指针去在数组内部的构造和析构过程中调用。实际上构造函数和析构函数往往是 inline 的糟糕人选,因为即使一个表面上看似空的构造函数,实际上编译器为此可能做了很多默认的工作。C++对于对象被构造很销毁时发生什么事做了各式各样的保证。当你创建一个对象,其每一个base class及成员变量会自动构造,当你删除一个对象,反向程序的析构行为亦会自动发生。在这些情况下,C++描述了什么一定会发生,但没有说如何发生。事情如何发生是由编译器的职责,不过有一点很情况,它们不会凭空发生,一定是有某些代码让它们发生,而那些代码:是由编译器在编译期代为产生安插到你的程序中去的,肯定存在于某些地方,有些时候就存在于构造函数和析构函数之中。所以我们可以想象,之前那个看似为空的构造函数实际上产生了大量的代码。
  11. 程序设计者必须评估将函数申明为 inline 的冲击:inline 函数无法随着程序库的升级而升级。换句话说,如果 fuc 是程序库中的一个 inline 函数,客户将其函数本体编进程序中,一旦程序设计者决定改变 fuc,所有用到 fuc 的客户代码都必须重新编译。这往往是大家不愿意看到的。然而如果 fuc 是 non-inline 函数,一旦有某些修改,客户只需要重新连接即可,远比重新编译的负担少得多。事实上,如果程序库采取动态连接,升级版函数甚至可以不知不觉的被应用程序所接纳。
  12. 对于程序开发来说,大部分调试器都无法对 inline 函数进行调试,毕竟如何在一个并不存在的函数内设立断点呢?虽然某些构建环境勉强支持 inline 函数的调试,大多数构建环境仅仅只能在调试期禁止 inlining 行为。

二. 总结

  1. 将大多数 inlining 限制在小型、被频繁调用的函数身上。这可使日后的调试过程和二进制升级(binary upgradability)更容易,也可使潜在的代码膨胀问题最小化,使程序的速度提升机会最大化。
  2. 不要只因为 function template 出现在头文件,就将它们声明为 inline。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 《Effective C++ 第三版》是一本关于C++高效编程的经典书籍,它涵盖了23个关键的C++编程技术,旨在帮助C++程序员成为更加高效和高质量的软件工程师。本书主要聚焦于面向对象编程和模板编程,以及C++语言的一些独特特性和语法,如函数重载、拷贝构造函数、移动语义、虚函数和多重继承等。本书帮助读者了解和掌握如何更好地使用C++,以提高代码的可读性、可维护性和可重用性。本书还覆盖了很多经常出现的编程问题,如内存管理、异常处理、并发编程等等,以及如何进行程序优化和测试。《Effective C++ 第三版》是一本全面而且深入的书籍,可以帮助C++ programmer成为真正的C++专家。无论是入门开发者还是有经验的程序员,都可以从中获得很多价值。此外,《Effective C++ 第三版》也是一本非常好的参考书籍,可以为学习和使用C++提供坚实的理论基础和实用的示例代码。 ### 回答2: "Effective C++" 是著名的程序设计书籍,作者是著名计算机科学家Scott Meyers。该书现已经推出第三版,也有了相应的PDF电子书。 这本书主要介绍了C++语言的一些重要概念和技术,帮助读者更好地理解C++的基本特性和高级编程技巧。第三版对前两版的内容进行了全面更新和完善,加入了最新的C++11和C++14标准中的变化和增强,包含了作者多年的实践和经验总结,增加了大量的实例和代码。 此外,"Effective C++"第三版还介绍了许多经典的C++编程问题和解决方案,例如对象生命周期管理、内存管理、资源共享、模板和STL应用等。这些问题在实际编程中经常会遇到,掌握了这些技巧有助于提升代码的质量、可靠性和效率。 总之,"Effective C++"第三版是一本十分实用、经典的C++编程书籍,它不仅适合初学者,也对有经验的程序员有重要的参考价值。无论是想提高自己的编程水平、规避C++程序中常见的错误,还是想进一步掌握现代C++编程技术的读者,都不可错过这本书。 ### 回答3: Effective C++ 第三版 pdf 是一本非常有价值的书籍,它是由 C++ 大师 Scott Meyers 所著,是 C++程序员必读的一本书籍。本书深入浅出地介绍了 C++语言中的一些非常重要的知识点和技巧,帮助读者更好地理解和运用 C++语言,提高编程的质量和效率。 在 Effective C++ 第三版 pdf 中,作者从多个方面对 C++语言进行了详细分析和解释,包括构造函数和析构函数的实现,运算符重载的使用,继承和虚函数的原理和应用,以及 STL等一系列的 C++语言特性和库函数的使用技巧。通过对这些重要知识点的深入讲解,读者可以很好地掌握 C++语言的内涵和精髓,提高自己的编程能力和技巧。 除此之外,Effective C++ 第三版 pdf 还提供了大量的实例和代码,能够直观地展示作者所说的知识点,并帮助读者更好地理解和掌握 C++语言的实际应用。读者可以通过反复练习和实践,逐渐掌握 C++语言的精髓和技巧,并能够应用到实际开发中,提高自己的编程能力和水平。 总之,Effective C++ 第三版 pdf 是一本非常有价值的书籍,它涵盖了 C++语言的重要知识点和技巧,同时提供了大量的实例和代码,能够帮助读者全面掌握 C++语言,提高自己的编程能力和水平。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值