欢迎来到天天文库
浏览记录
ID:12822034
大小:483.80 KB
页数:46页
时间:2018-07-19
《程序设计语言-学习笔记》由会员上传分享,免费在线阅读,更多相关内容在学术论文-天天文库。
1、函数调用开销对于没有参数函数调用的开销:1.调用函数和返回,所以需要执行一次call/ret指令对。2.函数内部,需要保护现场,所以需要把%ebppush到栈中,返回前,再pop出来。3.构造函数运行环境,将%ebp赋值为当前的栈顶%esp。则没有参数函数调用开销是5个指令。相比于没有参数函数调用的开销,带参数函数调用多2个指令,用于传递参数:movl-4(%ebp),%eaxmovl%eax,(%ebp)每个参数的传递时都需要2个指令。而如果是指针参数,则函数在使用时,还得需要2个指令。这么看,函数调用的开销还挺大的。所以,当一个函数很小且调用频繁时,应该用宏或内
2、联函数进行替代。 另外,虽然函数调用有开销,但除非有特殊的必要,该用函数的地方还是应该使用函数,否则会严重降低代码的可读性和可维护性。-------------------------------------------------------------------------------对于特别小的函数,编译器可能会将其编译为内联函数(将函数体直接展开),但对于普通的函数,函数调用函数有一些开销的。但是这个开销非常小,可以忽略不计。下面分析一下函数调用的开销。1。函数调用至少执行一次call指令和ret指令。2。如果函数中使用了局部变量或者函数带有参数,编译器会
3、生成方便访问调用参数和局部变量的参数(以VC6.0为例,在函数开头会修改ebp寄存器,在函数尾部会恢复ebp寄存器。3。如果函数中用到esi,edi,ebx,编译器会函数开头放置保护寄存器的指令,在函数尾部放置恢复寄存器的指令。4.如果一个函数时间复杂度非常小,且调用非常频繁,在C++中建议用inline函数,在C中建议用macro,除此以外,建议能用函数的地方,尽量定义函数。而不要大量的代码塞在一个函数中,这样既难阅读,又难维护。函数调用是有开销的:参数传递、保护现场,这些都需要CPU时间。但对于楼主的测试,由于函数代码较短,编译器很容易将它内联,于是变成没有开销
4、了。当然,即使是要追求效率,把所有的代码全部写在main函数中也不是什么好办法。个人认为一个C语言的函数,代码不应该超过100行,每行(包括空格和缩进)不超过80个字符。过长的函数会为调试和阅读带来极大的不便。另外,应该分析函数调用的开销在整个程序中所占据的比例。除非这个比例到了用户不能容忍的程度,否则就没必要去把多个小函数揉成一个巨大的函数。函数、宏、内联函数1、函数调用函数的开销大致可分两个部分:传递参数的开销和保存当前程序上下文信息所花费的开销。对于传递参数的开销而言,传递的参数越多开销就越大;对于保存当前程序上下文所花费的开销而言,函数越复杂需要花费的开销就
5、越大。2、宏宏在某种程度上可以代替函数,避免函数调用带来的开销。定义完宏之后,在编译程序时,用替代字符串代替程序中的宏。对于宏而言,虽然避免了函数调用带来的开销,但是增加了内存的开销。因为在每个应用宏的地方宏都会展开。 另外,宏易读性比较差,容易出现问题。例如:#defineMAX(a,b)((a)<(b)?(b):(a))voidmain(){ inta=10; intb=11; intc=0; c=MAX(a++,b++); cout<>c;}
6、 我们会发现c的结果为12,因为宏展开之后变为:((a++)<(b++)?(b++):(a++))并不是我们预想中的结果。故一般来讲最好不使用宏。3、内联函数 内联函数是避免函数调用开销的另一种方法,与宏类似,在程序编译是用内联函数替换函数调用。但只能运用与C++中,C中无法使用。与宏相比拥有参数类型检查的优点。 在C++类中,对于设置和读取私有变量的函数设置为内敛函数,有助于提高函数的效率。内敛函数的实现有两种方式,第一种是在函数定义时使用关键字inline,第二种方式时在函数定义时与函数体一起定义。4、递归与迭代 递归可以使程序显得短小精悍
7、,然而由于函数的多层调用,会严重影响程序的运行效率和内存使用效率。幸运的是在某种情况下,我们可以使用迭代来代替递归,避免函数调用开销。例子:递归版计算n的阶乘longFactorial(intn){ if(n==0) { return1; } else { returnFactorial(n-1); }}迭代版计算n的阶乘longFactorial(intn){ intfac=1; while
此文档下载收益归作者所有