内联函数与宏

news/2025/2/26 4:37:56

定义:

当函数被声明为内联函数之后, 编译器会将其内联展开, 而不是按通常的函数调用机制进行调用.

内联的工作机制

内联函数不是在调用时发生控制转移,而是在编译时将函数体嵌入在每一个调用处。编译时,类似宏替换,使用函数体替换调用处的函数名。一般在代码中用inline修饰,但是能否形成内联函数,需要看编译器对该函数定义的具体处理。


什么时候用内联函数

内联是用来消除函数调用时的时间开销。它通常用于频繁执行的函数。 一个小内存空间的函数非常受益。
如果没有内联函数,编译器可以决定哪些函数内联 。 程序员很少或没有控制哪些只能是内联的,哪些不是。 给这种控制程度,作用是程序员可以选择内联的特定应用 。


  • 优点:

只要内联的函数体较小, 内联该函数可以令目标代码更加高效. 对于存取函数以及其它函数体比较短, 性能关键的函数, 鼓励使用内联.

  • 缺点:

滥用内联将导致程序变得更慢. 内联可能使目标代码量或增或减, 这取决于内联函数的大小. 内联非常短小的存取函数通常会减少代码大小, 但内联一个相当大的函数将戏剧性的增加代码大小. 现代处理器由于更好的利用了指令缓存, 小巧的代码往往执行更快。

  • 结论:

一个较为合理的经验准则是, 不要内联超过 10 行的函数. 谨慎对待析构函数, 析构函数往往比其表面看起来要更长, 因为有隐含的成员和基类析构函数被调用!

另一个实用的经验准则: 内联那些包含循环或 switch 语句的函数常常是得不偿失 (除非在大多数情况下, 这些循环或 switch 语句从不被执行).

有些函数即使声明为内联的也不一定会被编译器内联, 这点很重要;
比如虚函数和递归函数就不会被正常内联.
通常, 递归函数不应该声明成内联函数.
(YuleFox 注: 递归调用堆栈的展开并不像循环那么简单, 比如递归层数在编译时可能是未知的, 大多数编译器都不支持内联递归函数). 虚函数内联的主要原因则是想把它的函数体放在类定义内, 为了图个方便, 抑或是当作文档描述其行为, 比如精短的存取函数.

内联函数与宏的比较

内联函数的功能和预处理宏的功能相似。相信大家都用过预处理宏,我们会经常定义一些宏,如

#define TABLE_COMP(x) ((x)>0?(x):0)

就定义了一个宏。
为什么要使用宏呢?因为函数的调用必须要将程序执行的顺序转移到函数所存放在内存中的某个地址,将函数的程序内容执行完后,再返回到转去执行该函数前的地方。这种转移操作要求在转去执行前要保存现场并记忆执行的地址,转回后要恢复现场,并按原来保存地址继续执行。因此,函数调用要有一定的时间和空间方面的开销,将影响其效率。而宏只是在预处理的地方把代码展开,不需要额外的空间和时间方面的开销,所以调用一个宏比调用一个函数更有效率。

但是宏也有很多的不尽人意的地方。

  1. 宏不能访问对象的私有成员。
  2. 宏的定义很容易产生二义性。

本文内容来自:
google开源代码风格指南,稍作整理修改。
http://zh-google-styleguide.readthedocs.io/en/latest/google-cpp-styleguide/headers/


http://www.niftyadmin.cn/n/3280961.html

相关文章

pdf转为ppt的超简单方法,就用这几个!

在我们的工作和生活中,PDF文件是不可或缺的文件格式之一。它以高准确性、整齐的页面排版和流畅的翻页而闻名,为我们处理文档提供了很大的帮助。然而,PDF文件的一个缺点是无法进行修改。当我们不小心输入错误数据或需要进行编辑时,…

5.17 英语单词小记

1.protocol n. 协议;草案;礼仪 vt. 拟定 vi. 拟定 过去式 protocolled或coled过去分词 protocolled或coled现在分词 protocolling或coling 例:pop Post office protocol发邮件协议2.assignvt. 分配;指派;[计][数] 赋值 vi. 将财…

include的顺序

项目内头文件应按照项目源代码目录树结构排列, 避免使用 UNIX 特殊的快捷目录 . (当前目录) 或 .. (上级目录). 例如, google-awesome-project/src/base/logging.h 应该按如下方式包含: #include "base/logging.h" 又如, dir/foo.cc 的主要作用是实现或测试 dir2/f…

Shell:setfacl缩小普通用户的权限

简介 我们在使用jumpserver的过程中,会向主机推送普通用户,但普通用户有上传下载文件的权限,要想对这些权限进行管控就比较困难,之前考虑通过将$PATH变量下的命令的权限设置为750,设置完发现用户无法正常登陆&#xff…

git 使用(二)

查看文件diff git diff # 比较当前文件和暂存区文件差异 git diff git diff # 比较两次提交之间的差异 git diff .. # 在两个分支之间比较 git diff –staged # 比较暂存区和版本库差异 git diff –cached # 比较暂存区和版本库差异 git diff –stat # 仅仅比较统计信息查…

Flask 快速入门

基于Python2.7的web框架,可以快速搭建后台服务器实现一些命令模拟操作 我之前用的命令 sudo pip install flask-login https://blog.csdn.net/u011054333/article/details/70151857转载于:https://www.cnblogs.com/-WML-/p/9057241.html

QtConcurrent Qt处理多线程

先学下单词,: concurrent 并发 有道词典结果n. [数] 共点;同时发生的事件 adj. 并发的;一致的;同时发生的 这个QtConcurrent的命名控件提供了可以用来实现程序多线程的高级api, 而不用使用低级的线程的原始…

(1)线程的常用方法 (2)线程的同步机制 (3)网络编程的常识

1.线程的常用方法 static void sleep(long millis) - 用于使得当前正在执行的线程进入休眠状态,休眠参数指定的毫秒(重点)。 static void sleep(long millis, int nanos) - 用于休眠参数指定的毫秒纳秒,1秒1000毫秒 1毫秒1000微秒 1微秒1000纳秒 int g…