读书笔记《Effective C++》条款30:透彻了解inlining的里里外外
来源:互联网 发布:lol出现一个网络问题 编辑:程序博客网 时间:2024/04/30 18:03
inline函数,可以调用它们又不需要函数调用所招致的额外开销。inline函数背后的整体观念是,将“对此函数的每一个调用”都以函数本体替换之。这样做可能增加目标码大小,引发代码膨胀。
换个角度说,如果inline函数的本体很小,编译器对“函数本体”所产出的码可能比针对“函数调用”所产出的码更小。
inline可以以隐喻方式将函数定义于class定义式内,任何在类内部定义的函数自动地成为inline函数:
class Person {public: int age() const//一个隐喻的inline,定义于class定义内 { return theAge; }private: int theAge;};
明确声明inline函数的做法则是在其定义式前加上关键字inline。
class Person {public:int age() const;private:int theAge;};inline int Person::age() const{return theAge;}inline函数应该在头文件中定义,这一点不同于其他函数。inline函数的定义对于编译器而言必须是可见的,以便编译器能够在调用点内联展开该函数的代码。此时,仅有函数原形是不够的。内联函数可能在程序中定义不止一次,只要内联函数的定义在某个源文件中只出现一次,而且在所有源文件中,其定义必须是完全相同的。把内联函数的定义放在都文件中,可以确保在调用函数时所使用的定义是相同的,并且保证在调用点该函数的定义对编译器可见。在头文件中加入或修改内联函数时,使用了该头文件的所有源文件都必须重新编译。
inline在大多数C++程序中是编译期行为。
inline是个申请,编译器可加以忽略。
大部分编译器拒绝将太过复杂(例如带有循环或递归)的函数inline,而所有对virtual函数的调用也都会使inline落空,因为virtual意味“等待,直到运行期才确定调用哪个函数”,而inline意味“执行前,先将调用动作替换为被调用函数的本体”。如果编译器不知道该调用哪个函数,你就很难责备它们拒绝将函数本体inline。
总结来说,一个表明上看似inline的函数是否真是inline,取决于你的建置环境,主要取决于编译器。幸运的是大多数编译器提供了一个诊断级别:如果它们无法将你要求的函数inline化,会给你一个警告信息。
此外,编译器通常不对“通过函数指针而进行的调用”实施inline,这意味对inline函数的调用有可能被inline,也可能不被inline,取决于该调用的实施方式:
inline void f() {}//假设编译器有意愿inline“对f的调用”void (*pf)() = f;f();//这个调用将被inline,因为它是一个正确调用pf();//这个调用或许不被inline,因为它通过函数指针达成在VS2013上测试,pf()可以编译通过。推断:如果要取得一个inline函数的地址,编译器就必须为此函数产生一个函数实体,无论如何,编译器无法交出一个“不存在函数”的指针。
实际上构造函数和析构函数往往是inline的糟糕候选人。构造函数和析构函数虽然“看”似简单,但编译器会在背后做很多事情,比如一个空的构造函数里面会由编译器写上对所有成员的初始化,如果将之inline,将会导致大批量的代码复制,所以不对构造函数和析构函数inline为好。
此外,程序库设计者必须评估“将函数声明为inline”的冲击:inline函数无法随着程序库的升级而升级。换句话说如果f是程序库内的一个inline函数,客户将“f函数本体”编进其程序中,一旦程序库设计者决定改变f,所有用到f的客户端程序都必须重新编译。这往往是大家不愿意见到的,这点和define类似。然而如果f是non-inline函数,一旦它有任何修改,客户端只需要重新连接就好,远比重新编译的负担少得多。如果程序库采用动态连接,升级版函数甚至可以不知不觉地被应用程序吸纳。
另外,大部分调试器面对inline函数都束手无策。
要点:
1.将大多数inline限制在小型、被频繁调用的函数身上。这可使日后的调试过程和二级制升级更容易,也可使潜在的代码膨胀问题最小化,使程序的速度提升机会最大化。
2.不要只因为function template出现在头文件,就将它声明为inline。
- 读书笔记《Effective C++》条款30:透彻了解inlining的里里外外
- Effective C++:条款30:透彻了解inlining的里里外外
- 《Effective C++》:条款30:透彻了解inlining的里里外外
- 《Effective C++》读书笔记之item30:透彻了解inlining的里里外外
- 条款30:透彻了解inlining的里里外外
- 条款30:透彻了解inlining的里里外外
- 条款30:透彻了解inlining的里里外外
- 条款30:透彻了解inlining的里里外外
- 条款30:透彻了解inlining的里里外外
- 条款30:透彻了解inlining的里里外外
- 《Effective C++》学习笔记条款30 透彻了解inlining的里里外外
- C++之透彻了解inlining的里里外外(30)---《Effective C++》
- 条款30 透彻了解inlining的里里外外
- 条款30:透彻了解inline的里里外外
- 条款29-30:为“异常安全”而努力是值得的与inlining的里里外外
- inlining的里里外外
- 读书笔记《Effective C++》条款42:了解typename的双重意义
- 透彻了解inline的里里外外——effective c++学习笔记
- 重温经典(xdoj1153)
- 《深入理解java虚拟机》学习笔记6——类加载机制
- 博客重整
- Java小球垂直下落垂直反弹代码
- 面试问题收集总结
- 读书笔记《Effective C++》条款30:透彻了解inlining的里里外外
- 在二叉查找树中插入节点-LintCode
- 汤晓鸥谈深度学习三大核心要素:算法设计、高性能的计算能力以及大数据
- JS运算符和语句
- 2017计蒜之道程序设计大赛初赛第二场题解
- citrix实施部署测试题库
- JS中window.onload事件详解
- 3.创建和维护索引库(Lucene6.0.0 CRUD)
- cpp