目录
一、缺省参数
二、函数重载
三、引用
3.1 引用的概念和定义
3.2 引用的特征
3.3 引用的使用
3.4 const引用
3.5 指针和引用的关系
一、缺省参数
• 缺省参数是声明或定义函数时为函数的参数指定⼀个缺省值,在调用该函数时,如果没有指定实参则采用该形参的缺省值,否则使用指定的实参,缺省参数分为全缺省和半缺省参数。(有些地方把缺省参数也叫默认参数)。
void Func(int a = 0)
{
cout << a << endl;
}
int main()
{
Func();
}
在这个函数中“int a”就是缺省形参,“10”就是缺省值,当使用该函数没有传参时就会使用缺省值,传参时就会使用指定参数。
• 全缺省就是全部形参给缺省值,半缺省就是部分形参给缺省值,C++规定半缺省参数必须从右往左依次连续缺省,不能间隔跳跃给缺省值。
void func(int a=1.,int b,int c=2)
{
}
上面这种给缺省参数就是错误的写法,必须从右往左连续缺省,中间不能断。
• 带缺省参数的函数调用,C++规定必须从左到右依次给实参,不能跳跃给实参。
• 函数声明和定义分离时,缺省参数不能在函数声明和定义中同时出现,规定必须函数声明给缺省 值。
避免声明和定义时缺省参数写的不一样,编译器就不清楚该用哪个缺省值。
二、函数重载
C++⽀持在同⼀作用域中出现同名函数,但是要求这些同名函数的形参不同,可以是参数个数不同或者类型不同,这样C++函数调用就表现出了多态行为,使用更灵活,C语⾔是不支持同⼀作用域中出现同名函数的。
1、参数类型不同
int Add(int left, int right) { cout << "int Add(int left, int right)" << endl; return left + right; } double Add(double left, double right) { cout << "double Add(double left, double right)" << endl; return left + right; }
这样在用到Add加法函数时就很舒服,不用考虑整型和浮点型
2、参数个数不同
void f() { cout << "f()" << endl; } void f(int a) { cout << "f(int a)" << endl; }
3、参数类型顺序不同
void f(int a, char b) { cout << "f(int a,char b)" << endl; } void f(char b, int a) { cout << "f(char b, int a)" << endl; }
注意:返回值不同不能作为重载条件,因为调用时也无法区分。
下面两个函数构成重载,但是调用时,会报错,存在歧义,编译器不知道调用谁
void f1()
{
cout << "f()" << endl;
}
void f1(int a = 10)
{
cout << "f(int a)" << endl;
}
给上了缺省值,在调用到 "f1()"时就会有歧义,直接报错。
三、引用
3.1 引用的概念和定义
引用不是新定义⼀个变量,而是给已存在变量取了⼀个别名,编译器不会为引用变量开辟内存空间,它和它引用的变量共用同⼀块内存空间。比如:水浒传中李逵,江湖上人称"黑旋风"。
类型&引用别名=引用对象
C++中为了避免引入太多的运算符,会复用C语⾔的⼀些符号,比如前面的>>,这里引用也和取 地址使用了同⼀个符号&,注意使用方法角度区分就可以。
int main()
{
int a = 0;
// 引⽤:b和c是a的别名
int& b = a;
int& c = a;
// 也可以给别名b取别名,d相当于还是a的别名
int& d = b;
++d;
// 这⾥取地址我们看到是⼀样的
cout << &a << endl;
cout << &b << endl;
cout << &c << endl;
cout << &d << endl;
return 0;
}
3.2 引用的特征
• 引用在定义时必须初始化
• ⼀个变量可以有多个引用
• 引用⼀旦引用⼀个实体,再不能引用其他实体
nt main()
{
int a = 10;
// 必须初始化引⽤
int& b = a;
int c = 20;
// 这⾥并⾮让b引⽤c,因为C++引⽤不能改变指向,
// 这⾥是⼀个赋值
b = c;
cout << &a << endl;
cout << &b << endl;
cout << &c << endl;
return 0;
}
3.3 引用的使用
• 引用在实践中主要是于引用传参和引用做返回值中减少拷贝提高效率和改变引用对象时同时改变被引用对象。
• 引用传参跟指针传参功能是类似的,引用传参相对更⽅便⼀些。
void Swap(int& rx, int& ry)
{
int tmp = rx;
rx = ry;
ry = tmp;
}
int main()
{
int x = 0, y = 1;
cout << x <<" " << y << endl;
Swap(x, y);
cout << x << " " << y << endl;
return 0;
}
• 引用和指针在实践中相辅相成,功能有重叠性,但是各有特点,互相不可替代,C++的引用跟其他语言的引用(如Java)是有很大的区别的,除了用法,最大的点,C++引用定义后不能改变指向, Java的引用可以改变指向。
• ⼀些主要用C代码实现版本数据结构教材中,使用C++引用替代指针传参,目的是简化程序,避开复杂的指针。
3.4 const引用
• 可以引用⼀个const对象,但是必须用const引用,const引用也可以引用普通对象,因为对象的访 问权限在引用过程中可以缩小,但是不能放大。
int main()
{
const int a = 10;
// 编译报错: “初始化”: ⽆法从“const int”转换为“int &”
// 这⾥的引⽤是对a访问权限的放⼤
//int& ra = a;
// 这样才可以
const int& ra = a;
// 编译报错: “ra”: 不能给常量赋值
//ra++;
// 这⾥的引⽤是对b访问权限的缩⼩
int b = 20;
const int& rb = b;
// 编译报错: “rb”: 不能给常量赋值
//rb++;
return 0;
}
• 不需要注意的是类似 int& rb = a*3; double d = 12.34; int& rd = d; 这样⼀些场 景下a*3的和结果保存在⼀个临时对象中, int& rd = d 也是类似,在类型转换中会产⽣临时对 象存储中间值,也就是时,rb和rd引用的都是临时对象,而C++规定临时对象具有常性,所以里就触发了权限放大,必须要用常引用才可以。
int main()
{
int a = 10;
const int& ra = 30;
// 编译报错: “初始化”: ⽆法从“int”转换为“int &”
// int& rb = a * 3;
const int& rb = a*3;
double d = 12.34;
// 编译报错:“初始化”: ⽆法从“double”转换为“int &”
// int& rd = d;
const int& rd = d;
return 0;
}
• 所谓临时对象就是编译器需要⼀个空间暂存表达式的求值结果时临时创建的⼀个未命名的对象, C++中把这个未命名对象叫做临时对象。
3.5 指针和引用的关系
C++中指针和引用就像两个性格迥异的亲兄弟,指针是哥哥,引用是弟弟,在实践中他们相辅相成,功能有重叠性,但是各有自己的特点,互相不可替代。
• 语法概念上引用是⼀个变量的取别名不开空间,指针是存储⼀个变量地址,要开空间。
• 引用在定义时必须初始化,指针建议初始化,但是语法上不是必须的。
• 引用在初始化时引用⼀个对象后,就不能再引用其他对象,而指针可以在不断地改变指向对象。 • 引用可以直接访问指向对象,指针需要解引用才是访问指向对象。
• sizeof中含义不同,引用结果为引用类型的大小,但指针始终是地址空间所占字节个数(32位平台下 占4个字节,64位下是8byte)
• 指针很容易出现空指针和野指针的问题,引用很少出现,引用使用起来相对更安全⼀些。
本篇内容就到这里,希望对各位有帮助,如果有错误欢迎指出。