- 1、给默认值的时候,只能从右向左给!!!
- 2、调用效率的问题(少了一句move的调用)
- 3、函数定义处可以给形参默认值,函数声明处也可以给形参默认值
- 4、形参给默认值的时候,不管是函数定义处给,还是函数声明处给,每一个形参的默认值只能出现一次!!!哪怕值一样也不可以!!!
- 函数的声明可以无数次,但是定义只能一次。
上面这样写是错误的,因为编译器从上到下编译,形参默认值是从右向左给
上面这样可行。因为编译器从上到下编译代码,默认从右向左的顺序看,b=20,a=10
- 如果只传入参数a,则b就是使用默认值20
- 如果给a和b都添加默认值,那么在调用的时候就可以不用传参数了。
注意:
- 我们给参数是从左向右给,实际上压栈是从右向左压,所以给默认值的时候必须是从右向左给!!!
下面这种写法是错误的!!!、
调用效率的问题:
- 带形参的默认值函数效率增高!少了1句move指令
#include2、inline内联函数using namespace std; //sum(, 20);这个写法是错误的 int sum(int a, int b = 20); int sum(int a = 10, int b); int main() { int a = 10; int b = 20; int ret = sum(a, b); cout << "ret:" << ret << endl; ret = sum(a); ret = sum();//和sum(20, 50);是一样的 ret = sum(a, 40); return 0; } int sum(int a, int b) { return a + b; }
面试问题:inline内联函数 和 普通函数的区别???
- 普通函数调用有标准的开销,介绍下函数的开销,我前面文章有讲过;
- 内联函数在函数的调用点直接把函数的代码进行展开处理了,没有函数的调用开销了;
- 如果函数在短时间内大量调用,可以将函数设置成内联函数
一个函数调用时,标准的函数调用过程:
- 从右向左压实参,压完实参后,执行call指令,将call指令的下一行地址入栈;
- 进入被调用函数中,sum的{,执行push ebp,将调用方main函数的地址入栈;然后给sum函数开辟栈帧,给sum函数栈帧初始化(linux下gcc和g++只负责开辟栈帧,不对帧的内存初始化)
- …
以上也叫做 函数调用过程中的开销(实参压栈、栈帧开辟、栈帧回退)。
其实sum函数只有x+y,是非常简单的,只有mov,add,move这几个指令,但是实际上确需要有函数调用开销,一次不多,如果千万次调用,就开销很大了。
inline内联函数:
- 在编译过程中,就没有函数的调用开销了,在函数的调用点直接把函数的代码进行展开处理了!!!
- inline函数在符号表中不再生成相应的函数符号!!!因为在函数调用点直接展开了!!!
- 但是不是所有的inline都会被编译器处理成内联函数 - 比如说递归;因为编译器是不执行代码的指令的,所以就不知道递归调用自己多少次。
- 而且如果这个函数代码量巨大,即使你写内联,编译器也不会内联处理,而且名字可能冲突了。
- 所以inline只是建议编译器把这个函数处理成内联函数!!!(是否inline成功,由编译器决定)
注意:
- 在debug版本上,inline是不起作用的,因为需要调试;inline只有在release版本下才能出现
反汇编代码:(表示vs2019上调试)
在Linux下查看是否内联函数:
- 在Linux下执行 g++ -c main.cpp -O2 (-c直接生成.o文件,不生成可执行文件)
objdump -t main.o(查看符号表 判断是否内联了,因为内联函数是没有符号的)



