引用变量是C++新增的一种复合类型。
引用是已定义的变量的别名。如变量a为变量b的应用,则可以交替使用a或者b来表示该变量。引用变量主要用于函数的形参,此时函数使用的是该变量的原始数据而不是变量的副本。其作用有些类似于指针,但在类设计中有更广泛的应用。
1. 创建引用变量
C++使用&符号来标记引用,如下:
int rats;
int & rodents = rats; // rodents称为rats的别名
int &表示指向int的引用。使用rats和rodents指向相同的值和内存单元。
这一点上与指针很类似,但与指针的区别在于引用必须在声明时进行初始化,而不能像指针一样先声明,再赋值。 如以下代码是不正确的:
int rat;
int & rodent;
rodent = rat; // 无法执行此语句
这种意义上来说***引用更接近于const指针,一旦与某个变量关联起来就始终无法改变。***语句int & rodents = rats;
实际上等效于int *const ptr = &rats;
2. 将引用用作函数参数
按引用传递允许被调用函数访问调用函数中的变量。如下程序展示了引用与指针传递的方法:
#include <iostream>
void swapr(int & a, int & b);// a, b为int的引用
void swapp(int * p, int * q);// p, q为int类型的地址
int main()
{
using namespace std;
int wallet1 = 300;
int wallet2 = 350;
cout <<"wallet1 = $" << wallet1;
cout <<" wallet2 = $" << wallet2 <<endl;
cout << "Using references to swap contents:\n";
swapr(wallet1, wallet2);
cout <<"wallet1 = $" << wallet1;
cout <<" wallet2 = $" << wallet2 <<endl;
cout << "Using pointers to swap contents:\n";
swapp(&wallet1, &wallet2);
cout <<"wallet1 = $" << wallet1;
cout <<" wallet2 = $" << wallet2 <<endl;
}
void swapr(int & a, int & b)
{
int temp;
temp = a;
a = b;
b = temp;
}
void swapp(int * p, int * q)
{
int temp;
temp = *p;
*p = *q;
*q = temp;
}
运行结果:
从函数调用来看,无法分辨按引用传递于按值传递,从函数定义中才能分辨:
void swapr(int & a, int & b);
引用必须在定义时进行初始化。而函数调用时使用实参初始化形参,因此函数的引用参数被初始化为函数调用传递的实参。因此swapr(wallet1, wallet2)
将形参a和b分别初始化为wallet1和wallet2。
如想使用传递给函数的信息而不修改它,同时还想使用引用,应使用const引用。
- 使用const可以避免无意中修改数据的编程错误
- 使用const使函数能够处理const与非const实参,否则只能接受非const数据
- 使用const引用使函数能够正确生成并使用临时变量
3. 将引用用于结构
如果函数按值返回一个结构,而不是结构的引用,则会将整个结构复制到一个临时位置,再复制到需要的变量;如果返回一个结构的引用,则直接将结构复制到需要的变量,效率更高。
**返回引用时,要避免返回函数终止时不再存在的内存单元引用。**如下代码:
const free_throws & clone2(free_throw & fit)
{
free_throws newguy;
newguy = ft;
return newguy;
}
newguy为函数中的临时变量,函数返回时已经不存在。同理,也应该避免返回指向临时变量的指针。
避免此类问题最简单的方法是返回一个作为参数传递给函数的引用。
4. 何时使用引用参数
使用引用参数的原因主要有两个:
- 程序员能够修改调用函数中的数据对象
- 通过传递引用而不是整个数据对象,可以提高程序的运行速度
对于使用传递的值而不做修改的函数:
- 如果数据对象很小,则按值传递;
- 如果数据对象是数组,则使用指针,这是唯一的选择,并将指针声明为指向const的指针
- 如果数据对象是较大的结构,则使用const指针或const引用
- 如果数据对象是类对象,则使用const引用。传递类对象参数的标准方式是按引用传递
对于修改调用函数中数据的函数:
- 如果数据对象是内置数据类型,则使用指针
- 如果数据对象是数组,只能使用指针
- 如果数据对象是结构,使用引用或指针
- 如果数据对象是类对象,则使用引用