内联函数真的可以提高程序执行效率吗
2016-05-05 23:16
288 查看
<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 + b int _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 pushecx 00169159 movedx,dwordptr [ebp-2F40h] 0016915F moveax,dwordptr x[edx*4] 00169166 pusheax 00169167 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 pushecx 00169001 movedx,dwordptr [ebp-2F1Ch] 00169007 moveax,dwordptr x[edx*4] 0016900E pusheax 0016900F 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 + b int 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 + b int 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下的反汇编实在是看不懂。但是内联作用不大是为神马???和书上讲的不一样呢???
相关文章推荐
- 下载图片webcollector
- PHP中yii2日期时间控件的使用
- linux命令(16):mv命令
- Java实现B树
- HDU 1331 Function Run Fun
- javascript之object对象
- css给父盒子加display:inline实现子盒子自动撑开 实现子盒子和父盒子都浮动
- Qt利用QGraphicsScene编写Word排版工具导出PDF
- 【第三章】 DI 之 3.1 DI的配置使用 ——跟我学spring3
- Redis Essentials 读书笔记 - 第七章: Security Techniques (Guard Your Data)
- [javaSE] 网络编程(概述)
- 广州宇信易诚科技有限公司面试题
- 关于单元测试的学习记录
- Config
- C++重复模板实例的处理
- Swift-获取本地所有图片并选取(Photos、PHAsset、CollectionView)
- 大数据学习资源
- STM32精确延迟1us和1ms的函数
- WPFINotifyPropertyChanged使用技巧
- BP神经网络的实例一则