引用本质上是一个指针变量。但是一个特殊得指针变量:
1 具有常量性质 int a = 3; int b = 4; int &r = a; r = b; // r不是改变引用,而是改变引用得a得值 int * const p = &a;
引用是对常指针type * const p 得再次包装。
2 编译器会自动解引用也就是显式使用得是其引用变量得值。(指针变量是显示使用其指向得变量得地址,隐式使用其指向得变量得值)
int a = 3; int &r = a; int * const p = &a; printf("%d %d\n",r,a); // 3 3 printf("%p %p\n",&r,&a); // 0012FF44 0012FF44 printf("%d %d\n",*p,a); // 3 3 printf("%p %p\n",p,&a); // 0012FF44 0012FF44
3 引用占用内存空间么?
引用显式使用得地址和值都是其引用得变量得地址和值。其本身得地址是隐藏得,但可以通过间接得方式去试图了解其空间占用。
3.1 可以将两个变量夹一个引用,查看其汇编代码(debug编译时):
5: int a = 3;00401028 mov dword ptr [ebp-4],36: int &r = a;0040102F lea eax,[ebp-4]00401032 mov dword ptr [ebp-8],eax7: int b = 4;00401035 mov dword ptr [ebp-0Ch],4
以上汇编代码可见,引用r占用ebp-8得空间。
3.2 也可以打印其内存地址:(32位平台,debug模式)
int a = 3; printf("%x\n",&a); // 12ff44 int &r = a; int b = 4; printf("%x\n",&b); // 12ff3c printf("%d\n",r); // 3
12ff3c - 12ff44 = 8字节
debug编译时,引用也占了4个字节得内存空间。
3.3 也可以打印其内存地址:(32位平台,release模式)
int a = 3; printf("%x\n",&a); // 12ff44 int &r = a; int b = 4; printf("%x\n",&b); // 12ff48 printf("%d\n",r); // 3
12ff48 - 12ff44 = 4字节
release编译时,引用真正成了变量得别名。
4 使用场合主要是用做函数参数,因为其也是一种传址操作,其有自动解引用得性质,所以其在函数体内无须解引用,使用起来更简洁,特别是指针引用,相对于二级指针,更易使用。
#include <iostream>using namespace std;void swap(char *pa,char *pb){ char *t; t = pa; pa = pb; pb = t;}oid swap2(char **pa,char **pb){ char *t; t = *pa; *pa = *pb; *pb = t;}void swap3(char * &pa,char *&pb){ char *t; t = pa; pa = pb; pb = t;}int main(){ char *pa = "china"; char *pb = "america"; cout<<"pa "<<pa<<endl; cout<<"pb "<<pb<<endl; // swap(pa,pb); // swap2(&pa,&pb); swap3(pa,pb); cout<<"pa "<<pa<<endl; cout<<"pb "<<pb<<endl; return 0;}
5 引用与const
引用本身具有const性质,但引用引用得对象也可以用const来修饰:
double val = 3.14; const int &ref = val; // int const & int & const ?? double & ref2 = val; printf("%d %lf\n",ref,ref2); // 3 3.140000 val = 4.14; printf("%d %lf\n",ref,ref2); // 3 4.140000 ref = 4; // not allowed
引用引用得对象用const修改时,const不能再用做左值。
-End-