(一〇二)内联函数

  1. 云栖社区>
  2. 博客>
  3. 正文

(一〇二)内联函数

零零水 2016-01-04 14:38:00 浏览593
展开阅读全文

元旦了,各种打不开博客。元旦结束,博客好了,是因为元旦放假程序员都回家了嘛?


————————————————————————————————

内联函数和普通函数有所区别。

 

普通函数需要①函数定义②函数原型③函数调用,具体调用形式是,先调用时,储存当前函数的内存地址(假设为地址A),然后调用函数,跳到被调用函数的内存地址(地址B),然后在地址B处依次执行,等执行完被调用的函数(或许还有返回值),再返回之前储存的地址A处。

 

内联函数,可以省略②函数原型(也可以不省略),但需要在函数定义和函数原型的函数头之前加上关键字inline(如果省略函数原型的话,则一般将函数定义放在函数原型的地方),

他的机制,是把函数代码,放在函数调用时的内存地址处,这样的话,无需像普通函数那样,从地址A处跳到地址B处,调用完再跳回来,而是地址A处之后的内存位置,就是原本是地址B处函数的代码内容。就像直接将函数命令放在调用处一样。

 

例如:

int main()
{
int a=x(1);

return 0;

}

int x(int m)

{
return m+3;

}

 

在普通函数时,int a的内存地址是地址A,而x函数被储存在地址B处(注意,BA并不一定相邻,或者说,几乎不会相邻)。于是程序访问内存时的顺序:地址A——地址B——地址A这样。

 

而在内联函数时,在int x(int m)之前加上inline,在main函数中,有点类似于:

int a={ 1 + 3 };

这样的形式。

 

由于内联函数是直接放在main函数中(而不是调用的时候才占用内存),因此,使用内联函数更耗费内存。但相对而言,使用内联函数的优点则是速度更快(因为不用在内存之中跳来跳去)。

 

但,由于在内存地址中跳来跳去速度其实很快,所以节省的时间的绝对值,并不大,除非该函数经常被调用(每次节约0.01秒,100次就是1秒了)。

 

内联函数的优点:速度更快——适合执行代码时间很短的函数;

内联函数的缺点:占用内存更多——不适合较长的函数。

 

 

编译器不允许使用内联函数的两种情况:

①递归函数——内联函数不允许自己调用自己;

②函数过大。

 

 

内联函数的使用方式:

①在函数原型和函数定义的函数头之前加上关键字inline即可;

 

②可省略函数原型,若省略,则将函数定义放置于函数原型处较好;

 

③其他同普通函数。

 

如代码:

#include<iostream>

inline int chengfang(int a)	//函数定义前置于函数原型处,并可省略函数原型
{
	return a*a;
}

int main()
{
	using namespace std;
	int b = chengfang(2);	//像普通函数那样调用内联函数
	int c = chengfang(5);
	cout << "b = " << b << ". c = " << c << endl;
	cin.get();
	return 0;
}

输出:

b = 4. c = 25


与内联函数对应的宏:

C语言中,使用预处理器语句#define来提供宏——内联代码的原始实现。

例如宏:#define SQUAR(X) X*X;

 

宏的特点是文本替换,而不像内联函数那样是函数调用——也就意味着,没有括号的情况下,结果和内联函数的结果不同。

define的代码:

#include<iostream>

#define square(x)	x*x;

int main()
{
	using namespace std;
	int a[5];
	a[0] = square(1);	//实质是1*1=1
	a[1] = square(2);	//实质是2*2=4
	a[2] = square(2 * 2);	//实质是2*2 * 2*2=16
	a[3] = square(2 + 2);	//实质是2 + 2*2 + 2=8
	a[4] = square(2 + 0);	//实质是2 + 0*2 + 0=2
	for (int i = 0;i < 5;i++)
		cout << "a[" << i << "] = " << a[i] << endl;
	system("pause");
	return 0;
}

输出:


a[0] = 1
a[1] = 4
a[2] = 16
a[3] = 8
a[4] = 2
请按任意键继续. . .


使用内联函数的代码:


#include<iostream>

inline int square(int x) { return x*x; }

int main()
{
	using namespace std;
	int a[5];
	a[0] = square(1);	//实质是1*1
	a[1] = square(2);	//实质是2*2=4
	a[2] = square(2 * 2);	//实质是(2*2) * (2*2)=16
	a[3] = square(2 + 2);	//实质是(2+2) * (2+2)=4*4=16
	a[4] = square(2 + 0);	//实质是(2+0) * (2+0)=2*2=4
	for (int i = 0;i < 5;i++)
		cout << "a[" << i << "] = " << a[i] << endl;
	system("pause");
	return 0;
}

输出:


a[0] = 1
a[1] = 4
a[2] = 16
a[3] = 16
a[4] = 4
请按任意键继续. . .

由上述两个例子可以看出,#define宏的效果,和inline内联函数的机制完全不同。

 

#define是文本替换,将括号里的内容直接赋值到表达式之中——而不是括号里表达式的结果。

 

inline是像函数调用那样,将表达式的值得出值的结果后,再放入函数内部的表达式之中。

 

特别是比如说:#define MM(m) m*m*m; 这样的宏,

当遇见调用int a=1; int b=MM(a++);时,

在代码中,b=1*2*3=6

而不是内联函数的b=1*1*1(因为a++是先执行完这行代码之后,a=a+1);

 


网友评论

登录后评论
0/500
评论
零零水
+ 关注