首先我们来介绍一下什么是引用:
- 引用
引用不是定义一个新的变量,而是给一个已经定义的变量重新起一个别名。
定义的格式:
类型 &引用变量名 = 已定义过的变量名
void TestReferencl()
{
int a = 1;
int b = a;
cout<<"a:address->"<<&a<<endl;
cout<<"v:address->"<<&b<<endl;
a = 2;
b = 3;
int& c = b;
c = 4;
}
引用的特点:
1. 一个变量可以取多个别名
2. 引用必须初始化
3. 引用只能在初始化的时候引用一次,不能再改变为引用其他的变量。
const引用
void reReferenc2()
{
int a = 4;
const int& b = a;
cout<<"b="<<b<<endl;
a = 5;
cout<<"a="<<a<<endl<<"b="<<b<<endl;
const int c = 4;
const int& d = c;
const int& e = 10;//常量具有常性,只有常引用可以引用常量
cout<<"c="<<c<<endl<<"d="<<d<<endl<<"e="<<e<<endl;
double f = 1.1;
//int& g = f;
//f是double类型,g是整形,f在赋值给g时要生成一个临时变量
//这个临时变量具有常性
//因此不能直接赋值
const int& g = f;
cout<<"f="<<f<<endl<<"g="<<g<<endl;
}
const引用要注意下面三点
1. 常量具有常性,只有常引用可以引用常量。
2. f是double类型,g是整形,f在赋值给g时要生成一个临时变量这个临时变量具有常性
因此不能直接赋值。
3. 引用只能使权限变小,不能使权限变大。
引用作为参数
首先我们来看下面的代码。
void Swap1(int left, int right){
int temp = left;
left = right;
right = temp;
}
int main(){
size_t a = 1;
size_t b = 2;
Swap1(a,b);
cout<<"a="<<a<<endl<<"b="<<b<<endl;
return 0;
}
那么问题来了,上面的代码可以完成a,b的交换吗?
显然不可以,形参作为非引用的方式传值,则生成临时变量接受实参的值,所以形参作为实参的拷贝是无法改变实参的内容的。
那么,下面这个代码可以吗?
void Swap2(int* pLeft, int* pRight){
int temp = *pLeft;
*pLeft = *pRight;
*pRight = temp;
}
int main(){
int a = 1;
int b = 2;
//Swap1(a,b);
Swap2(&a, &b);
cout<<"a="<<a<<endl<<"b="<<b<<endl;
return 0;
}
嗯,不错,我们传指针就可以成功的交换两数的值。那么继续看下面的代码,思考可以吗?
void Swap3(int& left, int& right){
int temp = left;
left = right;
right = temp;
}
int main(){
int a = 1;
int b = 2;
//Swap1(a,b);
//Swap2(&a, &b);
Swap3(a, b);
cout<<"a="<<a<<endl<<"b="<<b<<endl;
return 0;
}
咦,等等,写到这里我们似乎可以发现一些规律。
无论引用还是指针,在函数交换的时候就是直接对实参进行操作,所以可以交换成功。而直接传参,形参是实参的拷贝,貌似是对实参进行操作,其实改变的只是拷贝的值,所以无法完成交换。
利用引用传参可以提高程序的效率。
另外,当不希望在函数内改变参数x的值时,尽量使用常引用传参。
void ReadBigData(const bigData& x){
int a = x.array[100];
}
传值作为返回值&传引用作为返回值
int& Add(int d1, int d2){
//int Add(int d1, int d2){
static int ret = d1 + d2;
return ret;
}
int main(){
int a = 5, b = 4;
int c = Add(a, b);
cout<<"c="<<c<<endl;
return 0;
}
因为ret在Add的函数栈帧内临时存在,在函数调用结束之后就会销毁,所以返回这块内存的引用,可能有时候结果正确,但是会造成访问非法内存。
综上所述,我们可以得到下面的结论:
- 不要返回一个临时变量的引用。
- 如果返回对象出了当前函数的作用域仍然存在,则最好使用引用返回,因为这样更高效。
引用和指针的区别
- 引用只能在定义的时候初始化一次,之后不能改变其指向的的值(从一而终),指针变量的值可以改变。
- 引用必须指向有效的变量,指针可以为空。
- sizeof指针对象值得是对象地址的大小,sizeof引用指的是引用所指向的变量的大小。
- 指针和引用自增自间的意义不一样。
- 相对而言,指针比引用更安全。