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