目录
1.函数重载
1.1 函数重载的概念
1.2 C++支持函数重载的原理——名字修饰
2.引用
2.1 引用的概念
2.2引用的特性
2.3常引用
2.4使用场景
2.4.1 作参数
2.4.2 作返回值
2.4.3 传值,传引用效率比较
2.4 引用和指针的区别
函数重载时C++中的一个概念,C++允许在同一作用域中声明几个功能类似的同名函数,这
些同名函数的形参列表(参数个数 或 类型 或 类型顺序)不同,常用来处理实现功能类似数据类型
不同的问题。
int Add(int x, int y)
{
cout << x + y << endl;
return x + y;
}
double Add(double x, double y)
{
cout << x + y << endl;
return x + y;
}
比如这种,形参列表中参数类型不同。
void f()
{
cout << "abcd" << endl;
}
void f(int x)
{
cout << x << endl;
}
这种一个有形参,一个没有形参也能构成函数重载。
一段程序的运行要经过预处理,编译,汇编,链接,编译后会生成符号表,链接时就会到符号表中找寻不同的函数,为了区分两个函数名相同的函数,往往会对函数名进行一些修饰,这种修饰在不同的编译器下可能会不一样。
引用就是对一块已经开辟出的空间取一个别名
int a = 1;
这段代码意思是给一个四字节的的空间取了一个名字叫a,我们可以再对这块空间取一个名字
int& b = a;
这样b就是这块空间的别名,对b进行任何操作,也会对 a产生同样的效果。
引用在定义时必须初始化
引用一旦引用一个空间,就不能再引用别的空间
一个变量可以有多个引用
引用和被引用的对象必须是同一类型
int a = 1;
const int& ra = a;
对引用使用const进行修饰限定,便是常引用,引用可以缩小权限,和平移权限,但不能放大权限。 上面代码就是一段缩小权限。
const int a = 1;
const int& ra = a;
这段代码就是权限平移,引用后可对变量进行的操作与未引用相同。
//const int a = 1;
//int& ra = a;
这就是权限放大了,原变量是只读的,引用后可以修改,当然是不行的。 因此这么写编译器会编译报错。
C语言要实现交换两个变量值的功能必须使用指针
void Swap(int* x, int* y)
{
int tmp = *x;
*x = *y;
*y = tmp;
}
而C++中可以使用引用来传参
void Swap(int& x, int& y)
{
int tmp = x;
x = y;
y = tmp;
}
这样写方便了不少,至少不用麻烦地敲解引用操作符。
int& Add(int a, int b)
{
int c = a + b;
return c;
}
int main()
{
int& ret = Add(1, 2);
Add(3, 4);
cout << "Add(1, 2) is :"<< ret <
上面的代码就是一个引用为返回值的例子。上面例子中,打印结果可能是随机值,也可能是7,取决于编译器是否会在函数栈帧销毁后清理空间。
为什么会有这种结果呢?不妨来分析一下上面的代码。
上面的Add函数返回了c的引用,而在main函数中的ret接受了返回值后,Add函数的栈帧已经销毁了,这意味着Add函数返回了一个已经被释放的空间的别名,而这块被释放的空间会存放什么值,无从得知。
从上例可以总结出,函数的变量在函数调用结束,函数栈帧销毁后依然能存在,才能使用其引用作为返回值。
以值作为返回值返回或作为参数传递时,会生成值的一份临时拷贝,因此传值效率比较低,而传引用直接返回空间别名,或直接用空间别名作为参数传递,效率比值要高。
#include
struct s
{
int a[10000];
};
void f1(struct s a)
{
;
}
void f2(struct s& a)
{
;
}
int main()
{
struct s a;
size_t begin1 = clock();
f1(a);
size_t end1 = clock();
size_t begin2 = clock();
f2(a);
size_t end2 = clock();
cout << end1 - begin1 << endl;
cout << end2 - begin2 << endl;
return 0;
}
可以用这段代码测试下两种传参方式在效率上的差异。
语法的定义上,引用是指一块空间的别名,而指针在语法定义上是一块空间的地址,这导致在使用时便利程度上有所差异。
但是在底层的实现上,引用也是用指针实现的
int main()
{
int a = 10;
int& ra = a;
ra = 20;
int* pa = &a;
*pa = 20;
}
让我们来看看这段代码的汇编代码
可以看到对引用的指针,底层的实现是一致的。
引用对于使用者来说是更方便的。(保准用了引用再也不想用指针)
引用和指针的效率相差无几。