1.5 引用
1.?引用是什么
对于习惯使用C语言进行开发的朋友们,在看到C++中出现的&符号后,可能会犯迷糊,虽然在C语言中这个符号代表取地址符,但是在C++中它却有着不一样的用途,代表着引用的意思。掌握C++的&符号,有利于增强代码质量和提高代码执行效率。
引用是一种变量类型,它用于为一个变量起一个别名。
引用的声明方法是:
类型标识符 &引用名=目标变量名;
假设有一个变量a,想给它起一个别名r,可以这样写:
int a;
int &r=a;
定义引用r,它是变量a的引用,即别名。经过这样的声明后,a和r的作用都一样,都代表着同一变量。a和r占用内存的同一个存储单元,即具有同一地址。在声明一个引用变量时,必须同时使之初始化,即声明它代表哪个变量。函数执行期间,不可以将其再作为其他变量的引用。例1.9说明了引用的使用方法。
【例1.9】 引用的使用举例。
#include<iostream>
using namespace
std;
int main(){
int a=2;
int &r=a;
a=a+4;
cout<<a<<"
"<<r<<endl; // 因为a和r的值会同时变化,所以a和r的值都是6。
r=10;
cout<<a<<"
"<<r<<endl; // r变了,a也会变,所以a和r的值都是10。
return 0;
}
程序的执行结果是:
6 6
10 10
例1.9中展示了引用与变量的关系。r是a的引用,a变了,r的值也跟着变;r变了,a的值也跟着变。
2.?引用作为参数
引用一个重要的作用就是作为函数的参数。
【例1.10】 引用作为函数的参数举例。
#include<iostream>
using namespace
std;
void Mmin1(int
a,int b){
int temp;
if(a>b){
temp=a;
a=b;
b=temp;
}
}
void Mmin2(int
&a,int &b){ // 引用作为函数的参数
int temp;
if(a>b){
temp=a;
a=b;
b=temp;
}
}
int main(){
int a=30,b=20;
Mmin1(a,b); //
cout<<a<<"
"<<b<<endl; // a、b的值保持不变。
Mmin2(a,b);
cout<<a<<"
"<<b<<endl; // a的值是20,b的值是30. a、b的值被修改了
return 0;
}
程序的执行结果是:
30 20
20 30
例1.10中定义了两个求最小值的函数,其中Mmin1是将一般变量作为函数的参数,Mmin2则是将引用作为函数的参数。
将一般变量作为函数的参数,传给形参的是变量的值,传递是单向的。如果在执行函数期间形参的值发生变化,并不传回给实参。因为在调用函数时,形参和实参不是同一个存储单元。
使用引用传递函数的参数时,在内存中并没有产生实参的副本,而是对实参直接操作。当使用一般变量传递函数的参数时,当函数发生调用,需要给形参分配存储单元,形参变量是实参变量的副本;如果传递的是对象,还将调用拷贝构造函数。因此,当参数传递的数据较大时,用引用比用一般变量传递参数的效率更高,所占空间更少。
使用指针作为函数的参数虽然也能达到与使用引用同样的效果,但是在被调函数中同样要给形参分配存储单元,且需要重复使用“*指针变量名”的形式进行运算,这很容易产生错误且程序的阅读性较差;另一方面,在主调函数的调用点处,必须用变量的地址作为实参,这些都不太方便。
综上所述,引用是个有效率的选择。
3.?常引用
如果既要提高程序的效率,又要使传递给函数的数据不在函数中被改变,就应该使用常引用。常引用的声明方式是:
const 类型标识符 &引用名=目标变量名;
用这种方式声明的引用,不能通过引用对目标变量的值进行修改,在程序中使引用的目标成为const类型,从而保证了引用的安全性,如下所示:
int a;
const int
&r=a;
r=1; // 错误
a=1; // 正确
假设有如下函数声明:
string func1();
void
func2(string &s);
那么下面的表达式都是非法的:
func2(func1);
func2("hello");
原因在于func1()和"hello"都将产生一个临时对象,而在C++中,这些临时对象都是const类型的。因此,上面的表达式就是试图将一个const类型的对象转化为非const类型,这是非法的。
引用型参数应该在能被定义成const的情况下,尽量定义为const。