一、带有默认的函数
形参变量的默认值从右往左给,例如 int sum(int a,int b=20);
下面来看两个例子:
int sum(int a,int b=20);
int sum(int a,int b=20); //错误,因为在一个文件中,声明可以无数次,但默认值只能给一次
int sum(int a,int b=20);
int sum(int a=10,int b); //正确,编译器在编译时从上往下走,扫描到b时b已经有默认值了,故此句不受影响
在编译时,声明不占内存不产生符号,但是定义会。ps:#include<stdio.h>头文件中只有函数的声明,没有定义,定义都在libc.so中。
二、函数重载(函数名相同,参数列表不同)
C: 根据函数名称来判断是否重定义
C++:根据函数名称、参数列表来判断是否重定义
sum函数在.c文件中生成符号 sun *UND*,在.cpp文件中生成符号 sum_int_int .*text*
extern "C" //在此大括号中生成的符号是C语言的符号,这是C++独有的语法
{
int sum(int a,int b)
{
return a+b;
}
}
int sum(int a,int b);
int sum(float a,float b);
int sum(double a,double b);
以上都是可行的。
三、内联函数 inline(在调用点把代码直接展开)
1)内联函数和宏的区别
宏:发生在预编译阶段,无类型检查,不安全
inline:发生在编译阶段,有类型检查,安全
2)和普通函数的区别
普通函数调用需要开辟、回退栈帧,内联函数不需要。
内联函数定义可以写在头文件中,普通函数不能会导致重定义
普通函数生成的符号是globle的,而内联函数不生成符号
3)和static函数的区别
static函数需要开辟、回退栈帧,而内联函数不需要。
static函数生成的符号是local的,而内联函数不产生符号。
关于什么时候调用内联函数?
函数调用栈帧的开辟回退开销>函数执行的开销
4)只在release版本生效,debug版本不生效,debug版本中inline函数的调用也需要开辟、回退栈帧
5)对递归函数的调用不起作用
四、const
看const修饰什么把类型去掉,只看const右边
const int *p 修饰*p,*p不可修改,即不可解引用
int *const p 修饰p,p的指向不可修改
const int a=10;
int *const p=&a; //错误 p的指向不可修改,但是可以进行解引用操作,编译器认为你企图修改a的值,故报错
const int *p=&a; //正确 不能进行解引用操作,数据安全,a的值无法被修改
1、在C语言中:
const修饰的量叫常变量,常变量和普通变量唯一区别是:常变量定义以后,不能作为左值使用。
const不是必须初始化,在整个工程可见。
const修饰的常变量的值可以被修改
#include<stdio.h>
int main()
{
const int a=10;
int *p=(int *)&a;
*p=20;
printf("a=%d,b=%d\n",a,b);
return 0;
} //a=20,b=20
2、在C++中:
const修饰的量叫常量,可作为左值。
const的编译规则:所有使用常量名字的地方全部替换成常量的初始值
const修饰的常变量的值可以被修改
#include<stdio.h>
int main()
{
const int a=10;
int *p=(int *)&a;
*p=20;
printf("a=%d,b=%d\n",a,b);
return 0;
} //a=10,b=20
const必须初始化,生成的符号是local的,只在本文件可见。(如果想让整个工程可见,可以使用extern,告诉编译器将本要生成的local符号改为生成globle符号,例如 extern const int a=10)
当const引用一个编译阶段不明确的值的时候,常量退化成常变量
int b=20;
const int a=b;
int arr[a]={0}; //错误,常量退化成常变量,常变量不能作为左值
五、引用&
定义引用的表示方法与定义指针相似,只是用&代替了*。&符号做引用时其后必须紧跟变量名。
&符号前有类型就是引用,否则就是取地址。
int a=10;
int &b=a; //引用
int *p=&a; //对a取地址
b=20; //修改a的值
*p=20;
数组引用实例:
int arr[10]={0};
int **p=&arr; //错误
int (*p)[10]=&arr; //正确,等同于int (&p)[10]=arr; 右边的取地址符覆盖前面的指针得到一个引用变量
1)引用必须初始化,初始化的值必须要能够取地址,且一经定义就不能改变。
2)定义引用变量需要开辟内存。
3)访问引用变量时,编译器自动对引用变量进行解引用操作,访问的即是所引用变量的地址。