前言
今天讲函数重载原理和引用的相关知识。
一、函数名修饰规则
我们都知道,c语言是不允许函数名同名的,c++则可以通过函数重载实现,而c++函数重载原理就是函数名修饰规则
c语言:
在生成可执行程序的过程中,c语言把不同的函数名放进符号表里,把函数名当做地址,在两个函数名相同时,编译器无法分别,所以c语言不支持函数重载
c++:
而c++有函数名修饰规则,将原本相同的名字根据其参数的类型、个数、顺序而改变,然后放入符号表,可以区别,这也是返回值不同不能构成函数重载的原因之一,即函数名修饰规则与返回值无关
在我们眼中相同的函数名,经过编译器的处理之后,已经成了不同的名字
但函数名修饰规则每个编译器不同,具体的不必掌握
那么如果函数名修饰规则跟返回值有关,那返回值不同能不能构成函数重载?
答案也是不能,因为调用时是不写返回值的,只有返回值不同的话就无法区别调用的是哪个了
二、引用
1.概念
int a = 0;
int& b = a; // 引用
引用就像是起外号,这个新定义的变量名就是它的外号,既然是外号,那么外号和本来的名字指的就都是同一个人
稍微提一下,引用不开辟空间只是理论上的,但在实际上并不如此,它的底层是指针
2.特性
int main()
{
// int& b; // 引用在定义时必须初始化
int a = 0;
//像是一个人可以有好几个外号
int& b = a;
int& c = a;
int& d = b;
int x = 1;
// 赋值, 引用一旦引用一个实体,再不能引用其他实体
b = x;
return 0;
}
最后一条即一旦是一个变量的别名,就不能是其他变量的别名。
像是蛋哥是王斌的外号,那么蛋哥这个外号只属于他自己,别人不能再被叫蛋哥了
3.应用
1.传引用传参
引用在传指针的情况下会方便很多,可以不用传指针或者二级指针变成一级指针
因为传的是它的别名,可以直接修改别名来达到修改它的目的,而不必传地址解引用来改变
//c语言二级指针的玩法
//为了修改一级指针只能使用二级指针
void PushBack(ListNode** pphead, int x)
{
//......
}
// CPP,引用的玩法
void PushBack(ListNode*& phead, int x)//传一级指针的引用,就可以直接修改一级指针
}
//......
}
传引用传参(任何时候都可以用)
1、提高效率
2、输出型参数(形参的修改,影响的实参)
2.传引用返回
//C的接口设计
//读取第i个位置的值
int SLAT(struct SeqList* ps, int i)
{
assert(i < ps->size);
// ...
return ps->a[i];
}
//修改第i个位置的值
void SLModify(struct SeqList* ps, int i, int x)
{
assert(i < ps->size);
// ...
ps->a[i] = x;
}
//CPP接口设计
// 读 or 修改第i个位置的值
int& SLAT(struct SeqList& ps, int i)
{
assert(i < ps.size);
// ...
return (ps.a[i]);
}
使用c语言时必须写两个函数来分别完成读和写,因为返回第i个位置的值时,返回的是ps.a[i]的值,是常量,不能修改
使用c++时返回ps.a[i]的引用,那么就不止能读,还能改了
int& Add(int a, int b)
{
int c = a + b;
return c;
}
像是上面的情况,返回了c的引用,但是c出了函数作用域已经被销毁了,那就出现了一种类似野指针的情况,指向的变量已经没了,但是你还指向它,就会出现问题
这个并不是局部变量就一定不能返回引用,还是要看出了作用域销毁不销毁
这个灵活看待,主要看出了作用域是否销毁,而不是看是不是局部变量
传引用返回(出了函数作用域对象还在才可以用)
1、提高效率
2、修改返回对象
4.与const相关知识
1.基本概念
在引用的过程中
权限可以平移
权限可以缩小
权限不能放大
const int a = 0;
// 权限的放大
// int& b = a;//a被const修饰不能改变,b此时不能作为a的别名,
// b一旦成为a的别名,改变b就会影响a,这样就成了权限的放大
//int b = a; 可以的,因为这里是赋值拷贝,b修改不影响a
// 权限的平移
const int& c = a;
// 权限的缩小
//本来x是完全不受限制的
int x = 0;
const int& y = x;//现在y作为x的别名,不能修改,权限缩小
//但是x仍旧不受限制
权限的缩小像是原本叫齐天大圣,可以上天入地没有限制,当改名孙悟空后,就要老实点,多了限制
2.举例
类型转换时会先生成一个临时变量,然后再由临时变量把值给d,而临时变量具有常性,d此时不能作为临时变量的别名,d一旦成为临时变量的别名,改变d就会影响临时变量,这样就成了权限的放大,只有加了const,使d不能改变,才能作为临时变量的别名
下面的也是类似情况
稍微提一下,当本该销毁的变量加了引用修饰后,就会延长生命周期,随ret一起销毁
总结
今天讲了函数重载的原理函数名修饰规则,并解释了为什么c语言不能函数重载,还有引用的一些知识,包括它的基本概念和应用,还有与const相关的部分