1、带有默认值的函数:
int sun(int a,int b = 20)
{
return a+b;
}
int mian()
{
int a=10;
int b=20;
sum(a,b);
/*
mov eax,dword ptr[ebp-8]
push eax
mov ecx,dword ptr[ebp-4]
push ecx
call sum
add esp,8
*/
sum(a);
/*
push 14h
mov ecx,dword ptr[ebp-4]
push ecx
call sum
add esp,8
*/
sum(a,30);
/*
push 1eh
mov ecx,dword ptr[ebp-4]
push ecx
call sum
add esp,8
*/
return 0;
}
汇编可以看出,sum(a,b)和sum(a)相比,sum(a)节省了一个mov的时间,但是sum(a)和sum(a,30)相比并没有提高效率,都需要压一个数字常量进站。
给参数默认值时要从右往左给,
int sum(int a=10,int b);这样是不符合规则的。
sum(,b);
在声明中给出默认值是可以的,但是默认值只能给一次。
int sum(int a,int b=10);
int sum(int a,int b=10);
上述定义会报重定义错误。
int sum(int a,int b=10);这样是可行的,因为当编译器执行到第二行时,认为b已经有默认值了,当然这两句是不能交换顺序的。
int sum(int a=20,int b);
2、内联函数inline:编译期间在调用点直接把代码展开,不生成符号。
- inline与宏的区别:
宏在预编译阶段进程字符替换,但是无类型
检查
,不安全。而且无法调试。
inline在编译阶段展开代码,进行类型检查,安全。这是inline的优点之一——更安全。
- inline与普通函数的区别:
普通函数需要开辟栈帧,清理栈帧。
inline不需要开辟栈帧,也就不用清理栈帧。这也是inline的优点之一——效率高。
- inline与static函数的区别:
static函数需要开辟栈帧,清理栈帧,而inline不需要。
static函数生成符号,且属性为local,不能被其他文件引用。
inline函数不生成符号,但是可以被其他文件引用。
inline函数只是给编译器的一个建议,只在release版本生效,Debug版本不起作用,inline函数调用时也需要
栈帧
开辟和回退。因为inline函数不生成符号,写在其他.cpp文件中并不能被找到,所以函数的声明和定义都应该包含在头文件中。
既然inline函数不需要开辟栈帧,效率高,为什么不都用inline呢?这是因为不生成符号表就需要操作系统管理,反而会不方便。当开辟栈帧的开销大于函数执行的开销时,使用inline函数。
还有一点,inline函数对递归函数不起作用,因为inline函数调用时直接在调用点展开代码,但是递归函数在编译时并不知道调用几次。
3、函数重载
C:根据函数名生成符号;
C++:根据函数名和参数列表生成符号。
函数名相同,参数列表不同,且处于同一作用域,就构成函数重载例如compare函数。如果在main函数中定义int compare(int a,int b)不符合条件。
这里要注意,函数生成符号时和返回值无关,所以不能仅通过返回值不同判断。
bool compare(int a,int b)
{
cout<<compare(int,int)<<endl;
return a>b;
}
bool compare(double a,double b)
{
cout<<compare(double,double)<<endl;
return a>b;
}
bool compare(char *a,char *b)
{
cout<<compare(char*,char*)<<endl;
return strcmp(a,b) >0?ture:false;
}
int main()
{
compare(10,20);
compare(10.5,15.2);
compare("hello","world");
}
bool compare(float a,float b){ cout<<compare(float,float)<<endl; return a>b;}如果把double改成float,就会出现错误,因为 compare(10.5,15.2);在进行类型匹配时没有double型,就要进行类型转换,但是究竟是转换成int还是float不明确,所以会出错,改成compare(10.5f,15.2f);就没问题了。
4、C和C++的互相调用
C++调用C:
extern "C"//里面的符号按照C语言规则生成,只有C++才认识extern
{
int sum(int,int);
}
#ifdef __cplusplus//不管使用C还是C++编译都生成C语言代码
extern "C"
{
#endif
int sum(int a,int b)
{
return a+b;
}
#ifdef __cplusplus
}
#endif
5、const
int a = 10;
const int b =20;
int arr[b];
int *p = (int*)&b;
*p = 30;
int a1 = a;
int b1 = b;
C语言中:除了在编译时查看下b有没有做左值,其他与变量没有什么区别,所以arr[b]是不可行的。也可以不初始化。打印b 和*p的只都是30。
C++中:
cout<<*p<<endl;//结果为30
cout<<b<<endl;//结果为20
这是为什么呢?在编译时会把b替换成20,在编译期间就已经确定,所以运行时尽管p改变了b的值,输出的还是20。也就是说b就是一个常量,arr[b]是可以的,这个时候b必须初始化。
如果是const int b = a;就退化成常变量。
const int data = 30;//const修饰的变量生成的符号是local
extern const int data = 30;//加extern后生成的符号是global