内联函数真的可以提高程序执行效率吗

来源:互联网 发布:刷生死狙击金币软件 编辑:程序博客网 时间:2024/06/12 01:33

<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">内联函数</span>

定义:

        内联函数是指用inline关键字修饰的函数。在类内定义的函数被默认成内联函数,又称为内嵌函数。

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

        真实的函数调用过程如下所示,函数调用的工作都是与完成特定任务操作无关的额外开销。

规则:

1.对函数的内联声明必须在调用之前,因为内联函数的代码在程序运行时是直接嵌在调用处的,它不影响链接,只在编译时确定运行代码。因此编译时,在调用之前看到内联声明就十分必要。

2.内联函数应该尽可能的小,且要结构简单,这样嵌入的代码才不会影响调用函数的主体结构。

(1)、内联函数之后不要含义复杂的结构控制语句,如switch while,如果含有这些则编译的时候就会无视内联声明,直接当作普通函数处理。

(2)、内联函数适用于1-5行的小函数。

(3)、递归函数属于结构复杂的函数不能作为内联函数处理。

内联函数一般适用场合:

1.函数体适当小,这样就使嵌入工作容易进行工作,不会破坏原调用主体。

2.程序中特别是在循环中反复执行该函数,这样就使嵌入的效率相对高。

3.程序并不多出出现该函数调用,这样就使嵌入工作量相对较少,代码也不会剧增。

实例:

一个小例子,分别使用普通函数调用、内联函数和宏,观察三者运行的不同情况

Windows下运行(VS2013):

#include "stdafx.h"#include <iostream>#include <time.h>using namespace std;int calc1(int a, int b){returna + b;}inline int calc2(int a, int b){returna + b;}#define CALCE(a,b) a + bint _tmain(int argc, _TCHAR* argv[]){int x[1000] = {0};int y[1000] = { 0 };int z[1000] = { 0 };cout<<"使用普通函数测试开始"<<endl;clock_t t = clock();for (int i = 0; i< 1000; ++i) //代码无意义只是测试使用{for (int j = 0; j< 1000; ++j){for (int k = 0; k< 1000; ++k){z[i] = calc1(x[j], y[k]);}}}cout<<"使用普通函数用时:"<< (clock() - t) / CLK_TCK<<"秒"<<endl;cout<<"使用内联函数测试开始"<<endl;t = clock();for (int i = 0; i< 1000; ++i)//代码无意义只是测试使用{for (int j = 0; j< 1000; ++j){for (int k = 0; k< 1000; ++k){z[i] = calc2(x[j], y[k]);}}}cout<<"使用内联函数用时:"<< (clock() - t) / CLK_TCK<<"秒"<<endl;cout<<"使用宏测试开始"<<endl;t = clock();for (i nti = 0; i< 1000; ++i)//代码无意义只是测试使用{for (int j = 0; j< 1000; ++j){for (int k = 0; k< 1000; ++k){z[i] = CALCE(x[j], y[k]);}}}cout<<"使用宏用时:"<< (clock() - t) / CLK_TCK<<"秒"<<endl;system("pause");return 0;}



运行结果好像内联函数并不尽人意,将代码反汇编发现,只有宏定义真正实现了内嵌,内联函数还行继续调用,不知道什么原因。



//宏定义:z[i] = CALCE(x[j], y[k]);0016929F  moveax,dwordptr [ebp-2F64h]  001692A5  movecx,dwordptr x[eax*4]  001692AC  movedx,dwordptr [ebp-2F70h]  001692B2  addecx,dwordptr y[edx*4]  001692B9  moveax,dwordptr [ebp-2F58h]  001692BF  movdwordptr z[eax*4],ecx//内联函数:z[i] = calc2(x[j], y[k]);0016914B  moveax,dwordptr [ebp-2F4Ch]  00169151  movecx,dwordptr y[eax*4]  00169158  pushecx00169159  movedx,dwordptr [ebp-2F40h]  0016915F  moveax,dwordptr x[edx*4]  00169166  pusheax00169167  call        calc2 (0161028h)  0016916C  add         esp,8  0016916F  movecx,dwordptr [ebp-2F34h]  00169175  movdwordptr z[ecx*4],eax//普通函数:z[i] = calc1(x[j], y[k]);00168FF3  moveax,dwordptr [ebp-2F28h]  00168FF9  movecx,dwordptr y[eax*4]  00169000  pushecx00169001  movedx,dwordptr [ebp-2F1Ch]  00169007  moveax,dwordptr x[edx*4]  0016900E  pusheax0016900F  call        calc1 (0161352h)  00169014  add         esp,8  00169017  movecx,dwordptr [ebp-2F10h]  0016901D  movdwordptr z[ecx*4],eax

好像内联函数与普通函数的反汇编执行过程是一样的没啥区别,只有宏定义的是真正嵌入到程序中了。

Linux下运行效果(centos 7 g++4.8.2):#include <iostream>#include <time.h>using namespace std;int calc1(int a, int b){return a + b;}inline int calc2(int a, int b){return a + b;}#define CALCE(a,b) a + bint main(int argc, char* argv[]){int x[10000] = {0};int y[10000] = { 0 };int z[10000] = { 0 };cout<< "使用普通函数测试开始" <<endl;time_t t = time(NULL);for (inti = 0; i< 10000; ++i) //代码无意义只是测试使用{for (int j = 0; j < 1000; ++j){for (int k = 0; k < 1000; ++k){calc1(x[j], y[k]);}}}cout<< "使用普通函数用时:" << (time(NULL) - t) << "秒" <<endl;cout<< "使用内联函数测试开始" <<endl;t = time(NULL);for (int i = 0; i< 10000; ++i)//代码无意义只是测试使用{for (int j = 0; j < 1000; ++j){for (int k = 0; k < 1000; ++k){calc2(x[j], y[k]);}}}cout<< "使用内联函数用时:" << (time(NULL) - t) << "秒" <<endl;cout<< "使用宏测试开始" <<endl;t = time(NULL);for (int i = 0; i< 10000; ++i)//代码无意义只是测试使用{for (int j = 0; j < 1000; ++j){for (int k = 0; k < 1000; ++k){CALCE(x[j], y[k]);}}}cout<< "使用宏用时:" << (time(NULL) - t) << "秒" <<endl;//system("pause");return 0;}

运行结果好像也是不怎么样:


使用关键字强制内联:

inlineint calc2(int a, int b)__attribute__((always_inline));

这个语句可以去查查,好像很有用。

#include <iostream>#include <time.h>using namespace std;int calc1(int a, int b){return a + b;}inlineint calc2(int a, int b) __attribute__((always_inline));inlineint calc2(int a, int b){return a + b;}#define CALCE(a,b) a + bint main(intargc, char* argv[]){int x[10000] = {0};int y[10000] = { 0 };int z[10000] = { 0 };cout<< "使用普通函数测试开始" <<endl;time_t t = time(NULL);for (inti = 0; i< 10000; ++i) //代码无意义只是测试使用{for (int j = 0; j < 1000; ++j){for (int k = 0; k < 1000; ++k){calc1(x[j], y[k]);}}}cout<< "使用普通函数用时:" << (time(NULL) - t) << "秒" <<endl;cout<< "使用内联函数测试开始" <<endl;t = time(NULL);for (inti = 0; i< 10000; ++i)//代码无意义只是测试使用{for (int j = 0; j < 1000; ++j){for (int k = 0; k < 1000; ++k){calc2(x[j], y[k]);}}}cout<< "使用内联函数用时:" << (time(NULL) - t) << "秒" <<endl;cout<< "使用宏测试开始" <<endl;t = time(NULL);for (inti = 0; i< 10000; ++i)//代码无意义只是测试使用{for (int j = 0; j < 1000; ++j){for (int k = 0; k < 1000; ++k){CALCE(x[j], y[k]);}}}cout<< "使用宏用时:" << (time(NULL) - t) << "秒" <<endl;//system("pause");return 0;}

运行效果好像也不过如此,但是好像内联起到了一些作用:


具体的反汇编就不看了,因为Linux下的反汇编实在是看不懂。但是内联作用不大是为神马???和书上讲的不一样呢???




0 0
原创粉丝点击