C++ 11标准中提出了引用的概念,如果不加特殊声明,一般都是指左值引用。
引用实际上是一种隐式指针,它为对象建立了一个别名,通过操作符“&”来实现。其定义形式如下:
数据类型 & 表达式;
例如,下述定义了一个引用变量 ia,它是变量 a 的别名,对 ia 的操作与对 a 的操作完全一样:
int a=10; //定义整型变量a
int & ia=a; //定义引用变量ia,它是a的别名
ia=2; //把2赋给ia,也就是a
有关引用的说明如下:
1) 一个 C++ 引用被初始化后,无法再使用它去引用另一个对象,即引用不能被重新约束。
2) 引用变量只是其他对象的别名,操作它与操作原对象的效果完全相同。
3) 指针变量与引用变量的区别为:指针是一种数据类型,引用不是数据类型;引用和变量的数据类型必须相同,不能进行类型转换;指针和引用都可以指向其他变量,指针的语法更复杂,而引用的使用方法与普通变量相同。
4) 引用必须进行初始化,否则会系统报错。例如,下面的代码会提示 references must be initialized 错误,无法通过编译:
int b;
int &a; //未初始化的引用,无法通过编译,系统会报错
【实例 1】利用引用输出变量的值。具体代码如下:
#include
using namespace std;
int main()
{
int a;
int & ref_a =a; //定义引用变量 ref_a,它是 a 的别名
a=100;
cout << "a="<< a < cout << "ref_a="<< ref_a << endl; a=2; cout << "a="<< a < cout << "ref_a="<< ref_a << endl; int b=20; ref_a=b; //改变 ref_a cout << "a="<< a < cout << "ref_a="<< ref_a << endl; ref_a--; cout << "a="<< a < cout << "ref_a="<< ref_a << endl; } 程序运行结果为: a=100 ref_a=100 a=2 ref_a=2 a=20 ref_a=20 a=19 ref_a=19 C++11右值引用 右值引用是 C++ 11 中引入的新特性,其定义形式如下: 类型 && i = 被引用的对象; 左值与右值的区别在于,右值是临时变量,如函数的返回值,并且无法改变。例如: #include int get() { int i =4; return i; } int main() { int k =3; int& a =++(get()); //编译出错 int& a =++(get())+k; //编译出错 return 0; } 右值引用可以理解为对右值的引用,当右值引用初始化后,临时变量消失。例如: #include int get() { int i = 4; return i; } int main() { int && k = get()+4; // int & i = get()+4; //出错 k++; std::cout<<"k的值"< return 0; } 程序运行结果为: k的值9 右值引用只可以初始化于右值,但右值引用实质上是一个左值,它具有临时变量的数据类型。与左值引用相同的是: 一个右值引用被初始化后,无法使用它再去引用另一个对象,它不能被重新约束; 右值引用初始化后,具有该类型数据的所有操作。 C++使用引用传递函数参数 C++ 中,函数参数的传递方式主要有两种,值传递和引用传递。使用引用传递时,在调用函数中修改参数的值,其改变会影响到实际参数。 【实例 2】引用传递交换数值。定义 swap() 函数,参数为两个引用变量。主函数中输入两个值,调用 swap() 函数交换两个数值。代码如下: #include using namespace std; void swap(int & a,int & b) //定义 swap()函数,参数为两个引用 { int tmp; tmp=a; a=b; b=tmp; } int main() { int x,y; cout << "请输入x" << endl; cin >> x; cout << "请输入y" << endl; cin >> y; cout<<"通过引用交换 x 和 y"< swap(x,y); //调用 swap()函数,实现两个数的交换 cout << "x="<< x < cout << "y="<< y < } 程序运行结果为: 请输入x 37 请输入y 9 通过引用交换 x 和 y x=9 y=37 读者可以将本例与实例 1进行对比,会发现使用引用和使用指针传递参数的执行效果相同。这是因为引用本质上是一个隐式指针,而不是一个普通变量。 使用引用和指针作为函数参数,各有益处。引用必须被初始化为一个对象,且无法再指向其他对象,优点是函数中不用验证引用参数的合法性。 例如,下面的函数调用是非法的: void ValuePass(int & var) //定义函数 ValuePass(),使用引用作为参数 { var = 10; //修改参数的值 cout << var << endl; //输出参数 } int main(int argc, char *argv[]) { ValuePass(0); //非法的函数调用 return 0; } 程序中,如果 ValuePass 采用指针作为函数参数,则“ValuePass(0);”调用语句是合法的,但存在一定的隐患。这是因为 0 会被认为是空指针,而对空指针进行操作会导致地址访问错误。 因此,当指针作为函数参数时,函数体中通常需要验证指针参数是否为空。优点是用户可以随意修改指针参数指向的对象,这是引用参数所不具备的。