创建引用变量
引用变量,是已定义变量的别名。
c++中使用&符号来创建引用变量。
例如,将rodents定义为rats的别名,则可以使用以下代码:
int rats;
int & rodents=rats;
此时,rodents和rats指向相同的值和地址。
可以通过下面的代码来测试:
int rats=101;
int & rodents=rats;
cout<<"rats="<<rats<<",rodents="<<rodents<<endl;
rodents++;
cout<<"rats="<<rats<<",rodents="<<rodents<<endl;
//output
rats=101,rodents=101
rats=102,rodents=102
从这方面来说,引用和指针很像,但是有几点不同:
- 引用必须在声明的时候初始化,而不能先声明,再初始化。
- 引用一旦与某个定义关联起来,就讲一直效忠于它,不再改变。
将引用作为函数参数
这种参数传递的方法叫按引用传递,不同于按值传递,按引用传递可以直接修改实参的值。
以下为一个例子:
#include<iosteam>
void add1(int a);
void add2(int & a);
int main(){
using namespace std;
int a=1;
add1(a);
cout<<a<<endl;
add2(a);
cout<<a<<endl;
}
void add1(int a){
a++;
}
void add2(int & a){
a++
}
//output
1
2
我们也可以选择不修改原始数据的值,可以在函数中使用const
下面这个例子用来计算参数的立方:
#include<iosteam>
int cube1(int a);
int cube2(int & a);
int cube3(const int & a);
int main(){
using namespace std;
int a=3;
cout<<cube1(a)<<"=cube of "<<a<<endl;
a=3;
cout<<cube2(a)<<"=cube of "<<a<<endl;
a=3;
cout<<cube3(a)<<"=cube of "<<a<<endl;
}
int cube1(int an){
an*=an*an;
return an;
}
int cube2(int & an){
an*=an*an;
return an;
}
int cube3(const int & an){
an*=an*an;
return an;
}
//output
27=cube of 3
27=cube of 27
27=cube of 3
使用const修饰时,main函数中的值没有发生改变。
在上面的例子中,cube1和cube3实现的功能类似,为什么还要多此一举使用引用类型呢?
这是因为,在按值传递的函数中,编译器会自动生成一个形参的副本,也就是一个临时变量,来存储实参的值。当我们需要传递的参数内容较大时,会造成一定的内存浪费。
使用引用传递,则可以直接将实参的地址传递到函数中,不需要生产临时变量,节省空间和时间。
在结构体和类对象中,引用就显得十分必要。
将引用用于结构
使用结构引用参数的方式与使用基本变量相同,只需在声明结构参数的时候使用引用运算符&即可。
假设有如下结构体定义:
struct person{
string name;
int age;
}
//函数原型如下
void show(person & p1);
//如果不希望函数修改传入的结构,可以使用const
void show(const person & p1);
下面用一个例子来说明:
#include<iostream>
using namespace std;
struct person{
string name;
int age;
}
person & older(const person & p1,const person & p2);
void show(const person & p3);
int main(){
person father={'James',40};
person son={'Simon',18};
show(older(father,son));
}
person & older(const person & p1,const person &p2){
if(p1.age>p2.age)
return p1;
else return p2;
}
void show(const person & p3){
cout<<"name:"<<p3.name<<",age:"<<p3.age<<endl;
}
//output
name:James,ages:40
此程序是找出person中年龄较大的那一个。
关于语句show(older(father,son))
,有下面的解释。
首先,father作为第一个参数传递给了older(),这意味着,在older()中,p1指向的是father。
同理,son作为第二个参数传递给了older(),在older()中,p2指向的是son。
将两者的age属性进行比较后,将年龄较大的person结构体的引用返回,在此次的例子中,返回的是father,也就是说,返回的是最初传进来的father对象。
接下来,将older()的返回值作为参数传递给了show(),这意味着将father传递给了show()。
为什么要返回引用类型?
假设有这么一条语句:
p3=older(father,son);
如果older返回的是一个值,而不是引用,则编译器会把整个结构体复制到一个临时变量,再将这个临时变量拷贝复制给p3。但在返回值是引用时,将直接把father复制到p3,其效率更高。
还有一点要注意:
上述代码中,show函数的参数使用了const修饰,但older的返回值类型并没有const修饰,但程序依旧可以运行不报错,这是因为,在c++中,可以将一个非const变量赋给const类型,但不可以把一个const变量赋给非const类型。
参考资料:c++ primer plus 第六版 中文版