它实质上是变量的别名,我们可以看作他是变量的一个“外号”
创建方法
int rats;
int &rodents=rats;(必须在声明的时候就初始化,不可int &rodents;rodents=rats;)
在这里rodents与rats指向相同的内存单元与值。也就是说,rats与rodents 的值都相同
引用变量作为函数参数
引用变量作为函数参数的参数传递方法叫做引用传递,而在C语言中,大部分还是按值传递
引用传递是使用的是原始数据,而按值传递改变的是原始数据的副本就会出现下面的情况
swap(int a,int b); //这是按值传递
swap(int &a,int &b) //这是引用传递
假设函数的作用是交换两个数的顺序,那么,在主函数中调用时,学过C语言的都知道上面的那个不会起作用,这也就是我们常说的形参不可以改变实参,而下面那个是直接使用原始数据(也就是实参),所以能完成代码的相应的功能。
将引用作为返回值时,效率更加高,传统按值返回会先将返回值复制到一个临时位置,再将这个变量拷贝出来,而返回值为引用时,会直接拷贝。
定义方法如下
char*left(char *str,int n=3);
如果调用函数的时候我们没有给n赋值,也就是说直接left(&ch)(ch为char型变量),那么,编译器会认为男,如果我们赋值了就为我们赋予的值。
添加默认值应该注意函数声明默认值必须从右向左
调用的是由默认值也必须是从左向右连续的,比如left("hahha",2, ,,4)j就是不合法的
函数重载可以让我们可以使用多个同名函数,我们可以理解为英文单词,同词不同义,函数重载也是同名不同功能。
函数重载的关键是函数列表也叫函数特征标。函数特征标只与函数数目与函数类型有关,与函数名没有关系。如果两个都相同,特征标相同。在使用函数重载的时候,编译器会根据函数特征标确定使用的函数。编译器会把类型引用与类型原型视为同一个特征标。
函数重载简单而言就是函数名相同,参数列表不同,而参数列表的不同就是函数重载可以存在的缘由,每个重载函数都需要定义,这个是一定的。
char left(int);
char left(char*);
函数模板的目的是减轻我们的代码量,就比如我们要实现的一个数的乘方,但是我们需要的计算的数有整形,有浮点型,整形中有short,int ,long,那么,我们是不是需要一遍一遍复制粘贴呢,在c语言中,好像只能这样子,但在c++中,提供了函数重载大法。他可以使用一个函数模板,但是函数参数可以是不同类型的。
模板创建
template
void swap(T a,T y);
重载的模板
函数模板针对的是不同类型的函数参数但是函数参数的数目是一样的,参数的数目有所不同我们还是要使用函数重载,这样子我们可以看作一个函数模板为一个函数类,这一类函数的为一区别是函数参数的类型的不同,那么,在这个层面上,我们可以把这儿的函数重载称为函数类的重载。
说到底,函数重载的参数的数目不同,势必代表着函数的代码会有区别,所以我们必须声明还有定义多个函数,函数模板当然可以利用重载来完成,但是由于只有函数类型的不同,重复定义函数显得冗杂,所以我们才选择使用函数模板。
实例化分成隐式实例化和显示实例化,具体化为显示具体化。
隐式实例化在我们调用代码的时候完成,我们使用模板时,编译器并不会生成函数定义,他只是生成一个生成函数定义的方案,只有在调用代码的时候才会生成函数定义。这是编译器的默认的版本。
显示实例化:我们需要定义
template void Swap
或者template void Swap(int a,int b);
这样子直接命令编译器创建一个特定的实例。
显示具体化
定义方法
相比于显示实例化,多了个<>
template<> void Swap
或者去掉
具体化的意思就是说我们不想使用模板的代码,我们想实现其他的别的功能,也就是说我们想自己定义这个函数,我们就可以使用具体化。比如Swap(a,b);中实现a,b的互换,假如a,b是结构体,我们只想互换a,b中的部分变量,这就需要我们重新定义虚函,我们就可以使用具体化。
更详细的可以看一下下面大佬的文章
链接:http://blog.sina.com.cn/s/blog_62b1508e0100hl8a.html
函数的优先性
在参数匹配的情况下
非模板函数>显示具体化>显式化实例>常规模板
但是,无论怎么,参数匹配还是第一位的,也就是说特征标起了决定性作用。