引用(reference)是C++极为重要的一部分,本文对其用法进行简单总结。
1. 引用的基本用法
引用的关键字为&
,表示取地址的意思,引用变量定义如下:
int m = 1;
int &n = m; //定义
cout<<"n=:"<<n<<" m="<<m<<endl;
cout<<&n<<" "<<&m<<endl;
n = 2; //修改
输出为:
n=:2 m=2
0x75fe78 0x75fe78
从结果可以看出来,变量n和m地址是一样的,而且修改n,m也会改变,这与指针有这异曲同工之妙。可以理解把引用为数据的另一个称呼。
引用要在定义的时候就赋值,并且不能再去引用别的变量,这一点和常指针类似(指向不变的指针)。引用变量在使用的时候直接使用变量名即可,不用带&,带上&表示取地址。
2. 引用作为形参
将引用变量作为函数的形参,与指针作为形参类似,可以在函数内部对输入参数进行修改。
#include <iostream>
using namespace std;void swap(int &m, int &n) {int temp = m;m = n;n = temp;
}
int main(){int a = 1, b = 100;cout<<"before: a="<<a<<", b="<<b<<endl;swap(a,b);cout<<"after: a="<<a<<", b="<<b<<endl;
}
输出:
before: a=1, b=100
after: a=100, b=1
引用变量在使用的时候似乎比指针简洁一些,变量本身就代表了引用的数据,而指针则需要加上*。
3. 引用与指针的区别
引用和指针都可以对被引用(指向)数据进行操作,具有相似的功能,不过还是有一些区别:
①引用必须从一而终,不能再指向其他数据;指针可以随意改变指向。
②int & const p = a是非法的,因为引用本身就自带有“常量”的属性,不用再刻意限制;而int * const p = &a是合法。此外,虽然int & const p = a不合法,但是const int & p = a依旧是合法的,意思是引用的数据不可修改。
③指针可以有多级,引用不可以。int **p = &a合法,int &&p = a非法。
关于指针和引用的区别,有人认为引用其实就是指针的简单封装,而且引用是占有内存的,但是无法获取地址,不是简单的一份数据两个名字。因为如果在类中定义引用变量,用sizeof可以计算出引用确实占用了内存。为啥无法获取引用本身的地址,解释是编译器不想让我们获取。
4. const 引用
void swap(int &m, int &n) {int temp = m;m = n;n = temp;
}
int main(){int a = 1, b = 2;int &a1 = a; //合法int &a2 = a + 1; //非法int &a3 = a + b; //非法swap(a+1,a); //非法
}
从上边代码可以看到,不能引用临时变量,临时变量一般是表达式形式的,一般会储存在寄存器上且无法修改,寄存器是无法寻址的,所以也无法引用(指针也一样),同样,临时变量也不能作为实参传给引用形参。
这种限制,会使引用在使用的时候很不方便,但是借助const关键字,可以解决这一问题。在引用变量前边添加const关键字,就是告诉编译器,我不会去修改你的临时变量,编译器就会为临时变量分配内存,于是引用就可以用了(指针不行)。
void swap(const int &m, const int &n) {}
int main(){int a = 1, b = 2;int &a1 = a;const int &a2 = a + 1;const int &a3 = a + b;swap(a+1,a);
}
添加const后,这些代码就不会报错了。