点蓝色字关注“CurryCoder”

微信公众号:CurryCoder的程序人生

怕什么真理无穷,进一寸有一寸的欢喜


1.inline函数的爱恨两难

内联函数比宏优点好很多,详细原因请参见尽量以const、enum、inline替换#define 。调用内联函数不需要承受函数调用所导致的额外内存开销,编译器最优化机制通常被设计用来浓缩那些“不含函数调用”的代码,所以当一个函数为内联函数时,或许编译器就因此有内联对其执行语境相关的最优化。“世界上没有免费的午餐”,内联函数背后的整体思想是:对一个函数的调用都以函数本体替换它,但这同时会增加你的目标码大小。在一个内存有限的机器上,过度使用内联函数会造成程序体积太大。即使用有虚拟内存,内联函数造成的代码膨胀也会导致额外的换页行为,降低指令高速缓存器的命中率。另一方面来说,如果内联函数的本体很小,编译器针对函数本体所产生的码可能比函数调用所产生的码更小。因此,将函数设置为inline,确实导致更小的目标码和较高的命中率。

2.inline函数卑微在线求助

inline只是对编译器的一个申请建议,不是强制命令,编译器可以选择对你的建议置之不理。这项申请可以隐式声明也可以显式声明,隐式声明是将函数定义在类的内部,如下所示:

class Person{public:    // ...    int age() const {return mAge;}   // 隐式的内联函数private:    int mAge;};

显式声明的方法则是在函数定义式前面加上关键字inline,如下面函数模板:

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

上述显式的声明方法中,值得注意的一点是:inline函数和函数模板通常都被定义于头文件中。但是,函数模板未必一定是内联的!!!inline函数通常一定被放置在头文件中,因为大多数构建环境在编译过程中进行内联动作,为了将一个函数调用替换为被调用函数的本体,编译器必须知道那个函数是啥样。内联动作在大多数C++程序中是编译期的行为。函数模板通常也被放置在头文件中,因为它一旦被使用,编译器为了将它具体化,需要知道它的样子。某些构建环境中,可以在连接期执行模板具体化,只不过编译期完成具体化的动作比较常见。3.inline函数与虚函数的爱恨纠缠

大部分编译器拒绝将太复杂(带有循环或递归、switch-case语句)的函数设置为inline,而且所有对虚函数的调用也都会使inline失效。这是因为虚函数是直到运行期才会确定调用哪个函数,而inline函数意味着执行前先把调用动作替换为被调用函数的本体,编译器工作在编译期。如果编译器都不知道该调用哪个函数,你也就明白了为啥虚函数不建议设置为inline。更多详情原因请看这里https://www.jianshu.com/p/84a8335444dd

4.糟糕的内联选择:构造函数与析构函数

不要被你的眼睛所欺骗,下面子类构造函数真的是空的吗???

class Base{public:    // ...private:    string bm1, bm2;};

class Derived: public Base{public:    Derived(){}  // Derived构造函数真的是空的吗???    // ...private:    string dm1, dm2, dm3;};

当你使用new,动态创建的对象被其构造函数自动初始化;当你使用delete,对应的析构函数会被调用。当你创建一个对象时,基类及其每个成员变量都会被自动构造;当你销毁一个对象时,从子类开始执行析构动作。如果有个异常在对象构造期间抛出,该对象已构造好的那一部分会被自动销毁。你的程序内一定有某些代码让那些事情发生,这些代码即编译器在编译期间产生并安排在你代码中的某个地方。有时候,可能就存在于你的构造函数和析构函数中。上面表面上看起来空的Derived构造函数所产生的代码,如下所示:

Derived::Derived(){    Base::Base();    try{        dm1.string();    }    catch(...){        Base::~Base();        throw;    }

    try{        dm2.string();    }    catch(...){        dm1.string();        Base::~Base();        throw;    }

     try{        dm3.string();    }    catch(...){        dm2.string();        dm1.string();        Base::~Base();        throw;    }}

上面的代码并不能代表编译器真正产生的代码,因为真正的编译器会以更复杂的做法来处理异常。尽管如此,上面的代码已经能反映Derived的空白构造函数必须提供的行为。不论编译器在其内部所做的异常处理有多么复杂,Derived构造函数至少一定会陆续调用成员变量和基类两者的构造函数,而那些调用会影响编译器是否对此空白函数执行内联动作。最后,程序库的设计者必须知道:内联函数无法随着程序库的升级而升级。如果fun()是程序库中的一个内联函数,客户将fun()本体编进其程序中,一旦程序库设计者决定改变fun(),所有用到函数f()的客户端程序都必须重新编译。如果fun()是non-inline函数,一旦它有所修改客户端只需要重新连接即可。对程序开发而言,大部分调试器对内联函数都束手无策,因为你无法在一个并不存在的函数内部设置断点进行调试呢?哪些函数可以设置为inline呢?我的建议是:首先不要将任何函数声明为inline,或者将inline实施范围局限在那些一定可以成为inline的场合。5.总结(1) 将大多数inline行为限制在小型、被频繁调用的函数身上。这可以使以后的调试过程和二进制升级更容易,也可以使潜在的代码膨胀问题最小化。(2) 不要只是因为函数模板出现在头文件中,就将它们声明为inline。

觉得不错,请一键三连吧↓

string类有可以调换方向的函数吗_深度剖析C++中的inline函数相关推荐

  1. string类有可以调换方向的函数吗_C++中的string类的用法小结

    相信使用过MFC编程的朋友对CString这个类的印象应该非常深刻吧?的确,MFC中的CString类使用起来真的非常的方便好用.但是如果离开了MFC框架,还有没有这样使用起来非常方便的类呢?答案是肯 ...

  2. string类有可以调换方向的函数吗_String类中常用的操作

    一.获取: 1.获取字符串的长度(注意是方法,不是跟数组的属性一样的) int length(); 1 public static void getLength(){ 2 String s = &qu ...

  3. string类有可以调换方向的函数吗_关于String类的split()方法

    展开全部 split 方法:将一个字符串分割为子字符串,然后将结62616964757a686964616fe4b893e5b19e31333366306464果作为字符串数组返回. split 方法 ...

  4. string类有可以调换方向的函数吗_StringUtils类常用方法:转换、移除、替换、反转...

    一.转换 StringUtils中涉及大小写转换以及判断字符串大小写的方法如下: 1)StringUtils.capitalize(String str) 2)StringUtils.uncapita ...

  5. python2中可以使用print()函数吗_在Python2.x中使用print()(函数版本)

    我理解语句和表达式之间的区别,我理解Python3将print()转换为函数. 但是我在各种Python2.x解释器上运行了一个用括号括起来的print()语句,它运行完美,我甚至不需要导入任何模块. ...

  6. python函数助手_转jmeter(十五)函数助手

    由于时间和版本问题,其中有些内容和排版我做了修改和重新整理,使其更符合最新的jmeter版本. 一.使用jmeter函数助手 启动jmeter后,可以在JMeter的选项菜单中找到函数助手对话框(快捷 ...

  7. 【C语言进阶】带你深度剖析那些常见的字符函数(一)

    前言 在C语言的学习中,C语言中对字符和字符串的处理很是频繁,所以今天本文是针对有关字符串的函数进行深度剖析,下面我会介绍函数的功能,如何使用,参数,模拟实现等方面来进行讲述,希望本文对你有所帮助. ...

  8. matlab里inline定义矩阵,Matlab中的inline函数_matlab中inline函数

    Matlab中的inline函数 1.有时为了描述某个数学函数的方便,可以用inline()函数来直接编写该函数,形式相当于M-函数,但无编写一个真正的MATLAB文件,就可以描述出某种数学关系.其调 ...

  9. len函数python返回值类型_简单介绍Python中的len()函数的使用

    01状态机介绍 游戏中的状态机一般都是有限状态机,简写为FSM(有限状态机),简称状态机,是表示有限个状态以及在这些状态之间的转移和动作等行为的数学模型. 状态机的每一个状态至少需要有以下三个操作: ...

最新文章

  1. 求有多少个数是这个数的约数
  2. android广播面试题,Android相关面试题
  3. 最近研究Rest,这个东西还是个雏形,给个好用的参考地址吧
  4. Spring mvc json
  5. 【洛谷 3905】道路重建
  6. ajaxFileUpload 异步上传文件简单使用
  7. openEuler 高校开发者大赛报名启动!广阔天地,码出不凡
  8. 会java需要多久能学会python_学好Python,c++ 和Java要多久?
  9. C#--Winform开发常见注意事项
  10. Appium的工作原理
  11. Mac下Android 反编译
  12. 关于偏微分、全微分总结
  13. matlab coder 转 c语言,MATLAB Coder从MATLAB生成C/C++代码步骤
  14. linux qt 找不到 lgl,c ++ - Qt:找不到-lGL
  15. 【推荐】程序员必读的三十本经典巨作
  16. 【Centos】Docker停止容器服务后,磁盘I/O仍然迟迟不下降。(未解决)
  17. 用NDK-r25编译libpng
  18. WarShall算法求传递闭包(可达矩阵)
  19. 『曹大带我学 Go 』系列文章汇总
  20. 以太坊(一)——概述

热门文章

  1. 飞畅科技-工业以太网的应用现状及前景展望
  2. 光模块该如何使用,光模块的使用方法介绍!
  3. PDH-SDH光端机指示灯具体含义介绍
  4. 【渝粤题库】国家开放大学2021春2748动物常见病防治题目
  5. 小米miuiVS华为鸿蒙,华为鸿蒙2.0 vs 小米MIUI 12.5
  6. c语言中系统函数设定像素,在imag中对每个像素应用自定义函数的快速方法
  7. settimeout怎么用_怎么实现一个3d翻书效果
  8. android界面实现框架内页面跳转_KVM虚拟化管理平台的实现
  9. 无锡太湖学院计算机科学与技术宿舍,无锡太湖学院宿舍条件,宿舍环境图片(10篇)...
  10. 并发编程---线程queue---进程池线程池---异部调用(回调机制)