目录
缺省参数
1.)全缺省
2.)半缺省
函数重载
1.) 参数类型不同
2.) 参数个数不同
3.) 参数顺序不同
函数重载的原理:
!!!注意 !!!
引用
1.) 引用做参数
2.) 引用做返回值
引用和指针的区别:
缺省参数
顾名思义,就是函数的参数可以缺省,即我们在写函数的声明或定义的时候,可以让其参数有默认值。起作用是,在调用函数的时候,如果我们没有指定实参,则会采用该形参的缺省值。
例子:
#include <iostream>
using namespace std;
//形参n的缺省值10,若没有指定实参,则实参n的值为10
void test(int n = 10)
{
cout << "n :" << n << endl;
}
int main()
{
test();
test(1);
return 0;
}
输出结果:
缺省参数有以下几种:
1.)全缺省
顾名思义,全缺省的意思则是函数参数全部都有缺省值。
// 形参a 和形参b 都有缺省值
void test(int a = 10, int b = 20)
{
cout << "a: " << a << endl;
cout << "b: " << b << endl;
}
2.)半缺省
顾名思义,则是函数参数部分有缺省值,但是要注意的是,半缺省则必须从右往左开始。
// 形参a 没有缺省值,形参b 有缺省值
void test(int a, int b = 20)
{
cout << "a: " << a << endl;
cout << "b: " << b << endl;
}
为什么半缺省必须从右往左开始缺省?以下代码则可以解释
// 这是个错误的例子,从左往右开始缺省
void test(int a = 10, int b)
{
cout << "a: " << a << endl;
cout << "b: " << b << endl;
}
上述错误的例子,该如何调用函数test()?
假设我们都有指定的参数,test(1,2),这个没问题,实参a = 1, b = 2。
那,如果我们要采用形参的缺省值,使 a 采用缺省值10,b 的值为20 的话,是test(20),那这个20按照函数参数的定义顺序的话,是赋给a,而参数b则没有收到指定的值,则会出现错误。
函数重载
在学习C++的过程中,会经常遇到的知识点就是重载,其是C++的精华之一,可以说“不了解重载则是不了解C++”。函数重载是函数的一种特殊情况,C++允许在同一作用域中声明几个功能类似的同名函数,这些同名函数的 参数个数 或 类型 或 类型顺序 不同。
1.) 参数类型不同
例子:
#include <iostream>
using namespace std;
//参数类型不同
int Add(int num1, int num2)
{
cout << " Add(int num1, int num2) " << endl;
return num1+num2;
}
double Add(double num1, double num2)
{
cout << " Add(double num1, double num2) " << endl;
return num1+num2;
}
int main()
{
// 参数是两个int类型,调用Add(int num1, int num2)
Add(1,2);
// 参数是两个double类型,调用double Add(double num1, double num2)
Add(2.5,2.5);
return 0;
}
结果:
2.) 参数个数不同
例子:
#include <iostream>
using namespace std;
// 参数个数不同
void test()
{
cout << " test() " << endl;
}
void test(int a)
{
cout << " test(int a) " << endl;
}
int main()
{
// 参数个数为0,调用函数test()
test();
// 参数个数为1,调用函数test(int a)
test(0);
return 0;
}
结果:
3.) 参数顺序不同
例子:
#include <iostream>
using namespace std;
// 参数顺序不同
void test(int a, double b)
{
cout << " test(int a, double b) " << endl;
}
void test(double a, int b)
{
cout << " test(int a, double b) " << endl;
}
int main()
{
// 参数顺序为 int double,调用函数test(int a, double b)
test(1,2.0);
// 参数顺序为 double int,调用函数test(double a, int b)
test(1.0,2);
return 0;
}
结果:
函数重载的原理:
重载函数在编译的汇编阶段会生成一个自己的符号表,在不同环境下生成的符号表不同,例如在g++环境下,以void test(int a, double b)为例,会生成一个为<_z4testid>的符号表,其中4是函数名的长度,test为函数名,id为形参的类型及顺序。
!!!注意 !!!
因符号表中并不能区别函数的返回值的类型,因此函数的返回值的类型不同并不能构成函数重载!函数重载的构成的条件是 参数个数 或 类型 或 类型顺序 不同!!!
引用
引用是给已存在对的变量取一个别名,而不是新定义一个变量,编译器不会为引用变量开辟内存空间,它和引用的变量共用同一块内存空间,因此,在某些场景下,我们可以采用引用来直接对变量的值进行修改,这种方式比采用指针的方式方便。
例子:
void test()
{
int a = 10;
int& ra = a; //ra引用变量a
cout << " a: " << a <<endl;
cout << " ra: " << ra << endl;
++ra; //实际是对变量a进行修改
cout << " a: " << a << endl;
cout << " ra: " << ra << endl;
}
结果:
在使用引用的时候,要注意权限不能放大。例如引用一个const修饰的常变量时,要给const修饰引用。
void test()
{
const int a = 10;
// int& ra = a; 该语句编译时会出错,权限放大了
const int& ra = a;
}
引用有多种使用场景,例如做函数参数以及返回值等等。
1.) 引用做参数
// 引用做参数,效果类似指针,直接访问实参所在的内存空间
void Swap(int& num1, int& num2)
{
int tmp = num1;
num1 = num2;
num2 = tmp;
}
2.) 引用做返回值
// 引用做返回值
int& SelfIncrease(int& num)
{
return ++num;
}
在使用引用做返回值的时候,要注意返回的对象的生命周期是否在函数作用域之外,若返回的对象的生命周期不在函数作用域之外,则不该采用引用的方式。
//正确的例子
int& Count()
{
static int n = 0;
++n;
return n;
}
// 错误的例子
int& Add(int a, int b)
{
int c = a + b;
return c;
}
以值作为参数或者返回值类型,在传参和返回期间,函数不会直接传递实参或者将变量本身直接返回,而是传递实参或者返回变量的一份临时的拷贝,因此用值作为参数或者返回值类型,效率低下,尤其是当参数或者返回值类型非常大时,效率就更低。
而采用引用做参数或者返回值,在传参和返回期间,函数会直接传递参数或者变量的本身,效率得到了提高。
引用和指针的区别:
引用在语法概念上引用就是一个别名,没有独立空间,和其引用实体共用同一块空间
引用在底层实现上实际是有空间的,因为引用是按照指针方式来实现的。