本文为大便一箩筐的原创内容,转载请注明出处,谢谢:http://www.cnblogs.com/dbylk/p/4975474.html


今天我在优化公司项目代码的过程中,借助了Intel的VTune工具查看热点函数,发现有一个名为GetMatrixKey的函数调用频率很高,这个函数的主要作用是从一个矩阵数组中获取Matrix,其中还包含了指针检查与数组越界检查。考虑到这个函数的功能很简单,我就把它的实现挪到了头文件,并加上了inline关键字。随后我查看了一下这个函数的调用,发现它只在下面这个函数中被引用了(其中XXXX是类的名字,可以忽略掉):

// Author : 大便一箩筐 http://www.cnblogs.com/dbylk
D3DXMATRIX* XXXX::GetTransform(int nFrame) {
return GetMatrixKey(m_pTransform, m_nTransforms, nFrame);
}

我一看这个函数,马上就如法炮制,也把它挪进头文件,并加上了inline声明。

在继续进行了一些其他的优化后,我又运行了一下VTune,想要查看优化的结果。然后我惊奇地发现只有GetMatrixKey函数被内联了,GetTransform函数并没有被内联(VTune可以跟踪函数调用,如果函数被内联,则不会出现在函数的CPU利用列表中)。我记得当初学C++时,书上只是很笼统地说内联函数必须结构简单,但又没有定义什么才算“简单”函数。

随后,我去查了一下C++函数要满足什么条件才会被编译器内联,各个论坛中的人众说纷纭,下面是我整理粗略整理后得到的结果:

  • 函数体非常简单,通常为1~5行代码(这个应该不准确,因为我最开始被内联的那个函数就超过5行了,况且代码行数并不能和代码复杂度划等号)
  • 函数中不能包含循环语句、switch语句或异常处理语句(还有人说不能包含if语句,但经本人测试,包含if语句的函数是可以被内联的)
  • 函数中不能调用递归函数

然而,这些规则并不能解释GetTransform函数为什么没有被内联。随后,我又把GetMatrixKey函数取消内联,又进行了一次测试,结果发现GetTransform函数这一次被内联了,这说明内联函数A中可以调用其他函数B,但函数B不能是内联函数。

为此,我又采用了宏定义的方式实现GetTransform函数:

// Author : 大便一箩筐 http://www.cnblogs.com/dbylk
#define GetTransform(Key, nFrame) GetMatrixKey((Key).m_pTransform, (Key).m_nTransforms, nFrame)

结果发现GetTransform被“内联”(宏定义替换)了,GetMatrixKey函数没有被内联。

从上面的尝试可以得出一个结论,内联函数中不能包含其他内联函数,否则只有一个函数会被内联。


补充于2016-03-11:

内联函数可以说是用空间换时间的一种优化方式,因此它并不是一定能够提升程序性能的:如果一个实现比较复杂的函数可能在程序的很多个模块被调用,那么不内联可能会使程序具有更好的性能表现。因为内联会增加程序二进制代码的大小,这样会降低CPU Cache的命中几率,由此导致的开销可能远远超过内联优化得到的收益。

如果有足够的信心自己写的代码内联比不内联效率更高,可以使用C++的__forceinline关键字,这样一来编译器就会忽视优化选项,强制对函数执行内联处理。

关于inline函数的更多相关文章

  1. 理解C++的inline函数

    C++的inline函数就是编译器在编译代码时,将"对此函数的每一个调用"都以函数本体替换之,该过程发生在编译期间. inline函数的优点是,它可以省去函数调用所带来的额外开销, ...

  2. C++ inline函数

    本文主要记录了C++中的inline函数,也就是内联函数,主要记录了以下几个问题: C++为什么引入inline函数? 为什么inline能很好的取代表达式形式的预定义? inline函数的使用场合 ...

  3. inline函数的用法

    在c/c++中,为了解决一些频繁调用的小函数大量消耗栈空间或是叫栈内存的问题,特别的引入了inline修饰符,表示为内联函数.栈空间就是指放置程式的局部数据也就是函数内数据的内存空间,在系统下,栈空间 ...

  4. effective c++:inline函数,文件间编译依存关系

    inline函数 inline函数可以不受函数调用所带来的额外开销,编译器也会优化这些不含函数调用的代码,但是我们不能滥用Inline函数,如果程序中的每个函数都替换为inline函数那么生成的目标文 ...

  5. C++的优秀特性2:inline 函数

    (转载请注明原创于潘多拉盒子) Inline函数是C++的一个很小的特性,在不计较效率的情况下,这个特性似乎可有可无.然而,C++天生是为最为广泛的应用场景设计的,因此,总会有关于效率的问题.其实,除 ...

  6. 【转载】C++ inline 函数

    (一)inline函数(摘自C++ Primer的第三版) 在函数声明或定义中函数返回类型前加上关键字inline即把min()指定为内联. inline int min(int first, int ...

  7. C++中的inline函数

    内联函数: () 内联函数定义和作用: 将一个函数声明为inline,那么函数就成为内联函数.内联函数通常就是它在程序中每个调用点上“内联地”展开.从定义上看,内联函数跟一般函数不一样,一般函数调用的 ...

  8. 【转载】 c语言inline函数的使用

    c语言inline函数的使用 转载自:http://blog.chinaunix.net/uid-21843265-id-3056446.html 大学在教科书上学习过inline函数,定义为inli ...

  9. C Static Inline函数

    Inline函数 程序执行时,处理器从Memory中读取代码执行.当程序中调用一个函数时,程序跳到存储器中保存函数的位置开始读取代码执行,执行完后再返回. 为了提高速度,C定义了inline函数,告诉 ...

  10. C++ inline 函数

    (一)inline函数(摘自C++ Primer的第三版) 在函数声明或定义中函数返回类型前加上关键字inline即把min()指定为内联. inline int min(int first, int ...

随机推荐

  1. Python获取指定路径下所有文件的绝对路径

    需求 给出制定目录(路径),获取该目录下所有文件的绝对路径: 实现 方式一: import os def get_file_path_by_name(file_dir): ''' 获取指定路径下所有文 ...

  2. django--个人主页建立练习

    1.前端页面采用模板继承与动态模板 {% extends 'base.html' %} {% block content %} {% for article in article_list %} &l ...

  3. Android Wear - Design Principles for Android Wear(设计原则)

    ---------------------------------------------------------------------------------------------------- ...

  4. Java并发—并发工具类

    在JDK的并发包里提供了几个非常有用的并发工具类.CountDownLatch.CyclicBarrier和Semaphore工具类提供了一种并发流程控制的手段,Exchanger工具类则提供了在线程 ...

  5. 爬虫任务一:使用httpclient去爬取百度新闻首页的新闻标题和url,编码是utf-8

    第一个入手的爬虫小任务: maven工程 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi=" ...

  6. git log 查看提交历史

    文章出处http://blog.csdn.net/wh_19910525/article/details/7468549  git log  查看 提交历史 在提交了若干更新之后,又或者克隆了某个项目 ...

  7. MAC mysql install

    # linux 查看是否安装mysql   rpm -qa |grep mysql    yum 安装mysql      yum -y install mysql-server 1 download ...

  8. 卸载OpenJDK安装JDK

    卸载OpenJDK安装JDK rpm -qa | grep java rpm -qa | jdk java rpm -qa | grep java| xargs rpm -e --nodeps rpm ...

  9. System.Linq.Dynamic 动态查询

    安装 VS->工具栏->NuGet程序管理器,System.Linq.Dynamic 注意: 使用动态查询必须先调用AsQueryable()方法,因为动态扩展仅适用于实现IQueryab ...

  10. JSP与Servlet之后台页面单条删除与多条删除的页面跳转之实现

    单条删除页面跳转 1.首先打开JSP页面,找到删除 2.这个时候要把它改成servlet的URL,并决定要传给后台什么数据,例如我需要传一个待删数据的ID id并不是什么见不得人的东西(而且是后台也不 ...