引用变量
引用是已定义变量的别名
创建引用
int a;
int & b = a; // b为a的引用
- 引用(&),b 为 a 的别名
- 在函数引用时,必须对其初始化
- 一个变量可以有多个引用,一个引用只能指向一个实体
- a 和 b 指向的是同一块内存空间
将引用作为参数
引用作为函数参数,使得函数中的变量名成为调用函数程序中的变量的别名。这种传递称为引用传递,按引用传递允许被调用函数能访问调用函数中的变量。
void swapr(int & a,int & b); // 引用传递
void swapv(int a,int b); // 值传递
void swapp(int * a,int * b); // 指针传递
swap()
为交换函数,上面三个分别参数为引用、值、指针。经过我的一番测试发现。函数中的值传递并不能改变调用函数中a , b的值。引用和指针则可以。
引用时尽可能使用const
- 使用const能避免无意中修改数据的编程错误
- 使用const能够处理const和非const实参,否则只能接受非const数据
- 使用const引用使函数能正确的生成并使用临时变量
// 函数声明
double cube(double &a)
{
a = a * a;
}
// 调用函数
cube(x+2);
当函数cube()
的引用参数应该是可以修改的,但是传递的值是(x+2)并不是变量,所以编译时会出现错误。
但是,如果在引用前加上const
程序就能运行了,const
指定引用不能被修改,所以是否为变量也就不重要了。但是编译器会为其创建一个临时变量,保存(x+2),然后将 a 成为临时变量的引用。
那么什么情况下会创建临时变量呢?如果引用参数是const,则编译器会在下面两种情况生成临时变量:
- 实参的类型正确,但不为左值
- 实参的类型不正确,但可以转化为右值
结构的引用
引用非常适合结构和类。引入引用主要是为了用于这些类型,而非用于基本的内置类型。
引用这么高效为什么内置类型不使用引用呢?
《Effective C++》条款20:宁以pass by reference to const替换pass by value。其中有这么一句“如果你有个对象属于内置类型(例如int),pass by value 往往比pass by reference的效率高些”。说白了就是自己的东西用的更顺手一些。
使用结构变量引用参数和基本变量一用参数相同,就相当于别名,这里就不赘述了。
返回一个引用
引用既然能作为参数,那么能否作为返回值呢? 答案是肯定的。
为什么要返回引用呢? 毫无疑问,为了让程序效率更高。
// 声明函数:返回值是struct_a 类型的引用
struct_a & run(struct_a & a,const struct_a & b)
{
...
return a;
}
// dup接收run的返回值
struct_a dup = run(a,b);
当函数run()
返回值为类型时,dup接收的是一个结构,将把一个结构复制到一个临时位置,再将这个拷贝复制给dup,消耗空间且效率低。
但返回值为引用时,直接将a 复制到dup,效率更高
注意:在返回值为引用时不能返回栈空间的值,函数中创建的临时变量即使为引用,但是函数结束后栈空间的内容都会被销毁,返回将会出现错误。
总结
使用引用参数的原因:
- 修改调用函数中的函数对象
- 通过传递引用而不是整个数据对象,提高程序的运行速度
当数据对象较大的时候,第二个原因尤为重要。这些也是使用指针参数的原因。
那么指针参数和引用又有什么区别呢?
引用参数实际上是基于指针的代码的另一个接口,至此,引用展现了它的庐山真面目,其实它和指针在底层实现没什么两样,只是在使用上,有时引用会更加顺手。
那么什么情况下,应该使用何种传递参数的方式呢?
- 数据对象小且不做修改,例如内置类型和小型结构,按值传递。
- 数据对象数组,只能使用指针传递。
- 结构,引用和指针都可以
- 类,使用引用。