稀土 2018-04-12
比较的是 C89 和 C++99 这两个标准。
在C89里面没有带默认值的函数,C++99支持带默认值的函数。
在给形参默认值的时候,要按照从右向左的顺序。
可以在定义处给,也可以在声明处给。但是同一个变量的默认值只能给一次,给多次相同的默认值也不行。
调用的时候可以只传入没有默认值的实参,有默认值的可以不用传递。如果传了实参,函数调用时,在汇编上先压实参,按从右向左的顺序;如果没有传实参,编译器会将形参给的默认值直接压到栈上。
int sum(int a,int b=20) { return a+b; } int main() { int a = 10; int b = 25; sum(a,b); /* ebp esp mov eax ,dword ptr[ebp-8] //从内存中将b的值取出来放入寄存器中 push eax //把值压到栈上 mov ecx, dword ptr[ebp-4] push ecx call sum add esp,8 esp+=8 */ sum(a); sum(a,30); //和sum(a)在汇编上一样,没有区别 /* push 14h mov ecx, dword ptr[ebp-4] push ecx call sum */ return 0; }
所以,使用带有默认值的函数会提高效率,相当于节省了一个mov指令的周期。
这里比较的是C89和C++99,C99之后inline就和C++一样了。
(1)
内联函数:在函数的调用点,把函数的代码全部展开(编译过程)
宏:在预编译阶段处理
内联函数相当于一种更安全的宏,因为在预处理阶段不进行检查,只是进行替换,而编译阶段会进行类型检查,所以更安全。有内联函数后,尽量不用宏,因为用宏写的代码不能调试。
(2)
内联函数在调用点直接展开,不产生符号,只在本文件可见,在另一个文件不能通过声明在链接阶段定位到另一个文件中的内联函数,所以内联函数一般写在头文件中。
这样会出错,sum()重复定义,所以可以写成内联函数,就只在当前文件可见。
(3)
inline只在release版本起作用。在debug版本里面,inline函数的调用也需要栈帧的开辟和回退(主要是为了方便调试)。
而且inline只是对编译器的一个建议,最终是由编译器来决定是否处理成内联。
递归的函数不能处理成内联。
(4)
内联函数和普通函数的区别?
1.内联函数没有标准的函数栈帧的开辟和回退,而普通函数有。
所以函数过于短时,一般处理成内联函数,当调用函数的开销(栈帧开辟和回退)大于函数执行的开销时,用内联函数就省去了调用函数的开销。
2.内联函数不产生符号。
内联函数和static函数的区别?
1.都是文件可见(作用域)。
2.栈帧的开辟和回退不一样。调用static函数时有正常的栈帧开辟和回退,和普通函数一样。
3.static函数产生符号。
static函数和普通函数的区别?
static函数产生的符号都是local的,链接器不处理。
普通函数产生global符号。