C++引用(Reference)
引用(Reference)是 C++语言相对于 C语言的又一个扩充,类似于指针,只是在声明的时候用
引用可以看做是被引用对象的一个别名,在声明引用时,必须同时对其进行初始化。引用的声明方法如下:
由于引用和原始变量都是指向同一地址的,因此通过引用也可以修改原始变量中所存储的变量值,如例 2 所示。
【例 2】通过引用修改原始变量中的值:
如果我们不希望通过引用来改变原始变量的值时,我们可以按照如下的方式声明引用:
【例 3】不能通过常引用来修改原始值:
通过例 2 我们可以知道,通过引用我们可以修改原始变量的值,引用的这一特性使得它用于函数传递参数或函数返回值时非常有用。
【例 4】函数的引用传值:
【例 5】函数的普通返回值:
当我们将函数返回值声明为引用的形式时,如例 6 所示。虽然例 6 运行结果和例 5 是相同的,但例 6 中的 valplus() 函数在将 a 变量加上 5 之后,其运算结果是直接拷贝给 num2 的,中间没有经过拷贝给临时空间,再从临时存储空间中拷贝出来的这么一个过程。这就是普通的传值返回和引用返回的区别。
【例 6】函数的引用返回值:
在例 5 和例 6 中,我们就是为了避免这一点才采用的引用传递参数。普通的传值返回则不存在这样的问题,因为编译器会将返回值拷贝到临时存储空间后再去销毁 b 变量的。
【例 7】一个可能获取不到返回值的例子:
声明:《C++系列教程》为本站“54笨鸟”官方原创,由国家机构和地方版权局所签发的权威证书所保护。
&
取代了*
。引用可以看做是被引用对象的一个别名,在声明引用时,必须同时对其进行初始化。引用的声明方法如下:
类型标识符 &引用名 = 被引用对象
【例 1】C++引用示例:int a = 10; int &b = a; cout<<a<<" "<<b<<endl; cout<<&a<<" "<<&b<<endl;在本例中,变量 b 就是变量 a 的引用,程序运行结果如下:
10 10
0018FDB4 0018FDB4
由于引用和原始变量都是指向同一地址的,因此通过引用也可以修改原始变量中所存储的变量值,如例 2 所示。
【例 2】通过引用修改原始变量中的值:
int a = 10; int &b = a; b = 20; cout<<a<<" "<<b<<endl;程序运行结果是输出两个 20,可见原始变量 a 的值已经被引用变量 b 修改。
如果我们不希望通过引用来改变原始变量的值时,我们可以按照如下的方式声明引用:
const 类型标识符 & 引用名 = 被引用的变量名
这种引用方式成为常引用。如例 3 所示。【例 3】不能通过常引用来修改原始值:
int a = 10; const int &b = a; b = 20; //compile error a = 20;我们声明 b 为 a 的常引用,之后尝试通过 b 来修改 a 变量的值,结果编译报错。虽然常引用无法修改原始变量的值,但是我们仍然可以通过原始变量自身来修改原始变量的值,如例 3 中,我们用
a=20;
语句将 a 变量的值由 10 修改为 20,这是没有语法问题的。通过例 2 我们可以知道,通过引用我们可以修改原始变量的值,引用的这一特性使得它用于函数传递参数或函数返回值时非常有用。
1) 函数引用参数
如果我们在声明或定义函数的时候将函数的形参指定为引用,则在调用该函数时会将实参直接传递给形参,而不是将实参的拷贝传递给形参。如此一来,如果在函数体中修改了该参数,则实参的值也会被修改。这跟函数的普通传值调用还是有区别的。【例 4】函数的引用传值:
#include<iostream> using namespace std; void swap(int &a, int &b); int main() { int num1 = 10; int num2 = 20; cout<<num1<<" "<<num2<<endl; swap(num1, num2); cout<<num1<<" "<<num2<<endl; return 0; } void swap(int &a, int &b) { int temp = a; a = b; b = temp; }运行结果:
10 20
20 10
2) 函数引用返回值
在 C++ 中,非 void 型函数需要返回一个返回值,类似函数形参,我们同样可以将函数的返回值声明为引用。普通的函数返回值是通过传值返回,即将关键字 return 后面紧接的表达式运算结果或变量拷贝到一个临时存储空间中,然后函数调用者从临时存储空间中取到函数返回值,如例 5 所示。【例 5】函数的普通返回值:
#include<iostream> using namespace std; int valplus(int &a); int main() { int num1 = 10; int num2; num2 = valplus(num1); cout<<num1<<" "<<num2<<endl; return 0; } int valplus(int &a) { a = a + 5; return a; }在例 5 中,valplus() 函数采用的是普通的传值返回,也即将变量 a 的结果加上 5 之后,将结果拷贝到一个临时存储空间,然后再从临时存储空间拷贝给 num2 变量。
当我们将函数返回值声明为引用的形式时,如例 6 所示。虽然例 6 运行结果和例 5 是相同的,但例 6 中的 valplus() 函数在将 a 变量加上 5 之后,其运算结果是直接拷贝给 num2 的,中间没有经过拷贝给临时空间,再从临时存储空间中拷贝出来的这么一个过程。这就是普通的传值返回和引用返回的区别。
【例 6】函数的引用返回值:
#include<iostream> using namespace std; int & valplus(int &a); int main() { int num1 = 10; int num2; num2 = valplus(num1); cout<<num1<<" "<<num2<<endl; return 0; } int & valplus(int &a) { a = a + 5; return a; }此外,我们还需要注意一个小问题。如果我们将例 6 中的 valplus() 函数定义成例 7 中所示的形式,那么这段程序就会产生一个问题,变量 b 的作用域仅在这个 valplus() 函数体内部,当函数调用完成,b 变量就会被销毁。而此时我们若将 b 变量的值通过引用返回拷贝给变量 num2 的时候,有可能会出现在拷贝之前 b 变量已经被销毁,从而导致 num2 变量获取不到返回值。虽然这种情况在一些编译器中并没有发生,但是我们在设计程序的时候也是应该尽量避免这一点的。
在例 5 和例 6 中,我们就是为了避免这一点才采用的引用传递参数。普通的传值返回则不存在这样的问题,因为编译器会将返回值拷贝到临时存储空间后再去销毁 b 变量的。
【例 7】一个可能获取不到返回值的例子:
int & valplus(int a) { int b = a+5; return b; }
声明:《C++系列教程》为本站“54笨鸟”官方原创,由国家机构和地方版权局所签发的权威证书所保护。