c++中内敛函数_内联函数C++

背景

当程序调用一个函数时,实际上有一些额外的开销。函数调用会使程序跳转到另一个地址(函数的地址),并在函数结束时返回,如以下的函数示例。简单函数示例

假如上述函数编译后的汇编代码如下:简单函数对应的汇编代码

其中"sp"指的是堆栈指针,每个程序运行时,都有一个独立的堆栈,堆栈里放本地变量和返回地址(当调用一个函数时,那个函数的返回地址要放在堆栈里)。上述函数的执行过程具有以下几步:

(1)sp+8,即在堆栈里留出8个字节的空间,用于存放a和b两个变量;

(2)将4装入ax中,ax是一个主要用来做运算的寄存器;

(3)将ax里的值移到sp[-8]的地址处,即相当于源程序中的a=4;

(4)将sp[-8]的值移动到寄存器ax中,因为在函数fun里用到了a的值(把a赋值给value),这个步骤其实可以优化;

(5)将ax压入堆栈,相当于把函数的参数value压入堆栈,即在调用函数之前,需要将其参数压入堆栈,因此,函数的参数和本地变量的地位是一样的;

(6)调用函数,call是一条指令,首先将程序下一条指令的地址压入堆栈(以便返回),其次是转到_fun_int的位置开始执行;

(7)执行函数fun()的内容,@sp[-8]为函数的参数值,即value=4,将返回值装入ax中;

(8)找到返回的地址,将返回值赋给变量b

(9)把之前压入的ax(也就是临时变量value)弹出堆栈。函数的大致执行过程

因此,调用函数时,程序需要将送给函数的参数、返回地址放入堆栈,如果函数有临时变量,还需要将临时变量都放入堆栈,接着准备函数的返回值,函数返回时,需要将之前压入(push)堆栈的东西全部弹出(pop),可见,一个简单的函数过程需要许多额外的步骤。整个过程类似于我们在阅读文章时停下来看脚注,在阅读完脚注后返回到以前阅读的地方,来回跳跃并记录就需要额外的开销。

内联函数(inline)

内联函数与常规函数之间的主要区别不在于编写的方式,而在于C++编译器如何将它们组合到程序中。对于内联函数,编译器将使用相应的代码替换函数调用,也就是将函数体中的代码嵌入到被调用的地方去。这样处理,使得程序无需跳转到另一个位置执行代码,再跳回来,从而加快运行速度。

因此将原来的代码修改成:修改后的代码

而实际生成的代码是:实际生成的代码

编译结果里面并不会出现那个函数,内联函数仍旧保持了函数的独立性(函数有自己的空间,有自己的变量,函数调用时需要类型检查),只是不去真正地调用函数而已,函数类型检查这个步骤依然存在(由编译器完成),因而不会增加程序运行时的负担。

注意事项

对于一般的函数,其声明放在.h文件中,实现放在.cpp里,在其他文件里使用该函数时,只需要包含.h文件即可。inline函数可以这样做吗?不可以,编译会报错。如下:内联函数错误示例

为什么会报错,因为在编译主函数时,根据头文件知道有一个函数是inline,但是不知道这个函数的body,因此无法按照inline的规定将其函数体的代码插入到主函数中,就将这个函数当成了普通的函数。而在编译该内联函数的.cpp时,由于编译器发现是一个内联函数,就不会生成相应的代码。因此链接器在链接两个源文件时报错,main需要调用函数,而那个函数却不存在。

因此内联函数的body应该直接写在头文件里(不需要对应的.cpp),然后被包含到其他的源文件,此时的内联函数不再是定义,其实就是个声明。

要不要用内联函数内联函数的代码会被插入到调用处,如果程序有好几处调用该函数,程序就会变长,因此内联函数牺牲了代码的空间,降低额外运行开销,加快了程序运行的速度。

内联函数比C语言的宏定义好,如 :

#define SQUARE(X) X*X

a=SQUARE(5.0) 即为a=5.0*5.0,这并不是通过值传递实现的,而是通过文本替换实现的,假如输入的参数不是5.0,而是一个字符串呢?这种宏定义不能进行类型检查,而内联函数可以,因此更安全 。

如果编译器发现函数很长,会自动拒绝该函数作为内联函数。

递归不能作为内联函数,因为递归一定需要借助堆栈的压入和弹出实现功能。

对于C++类的成员函数,如果在函数声明的地方就给出了函数体,这些函数默认就是内联函数,如下:类里面默认的内联函数

类的成员函数“getColor()”和“setColor()”是内联函数,它们的调用相当于直接访问属性“color”,运行效率较高,但是通过函数去访问类的属性,符合面向对象编程的思想,函数使得类的属性与外界产生隔绝。

6. 如果函数很小,又在程序中多次被调用(如一个循环中),编译器会自动将其作为inline函数。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值