栗子
- 第一次
int x = 0;
int* p = &x; // p is a pointer to X
int& r = x; // r is a reference to X
int x2 = 5;
对于int x = 0,x是一个整数变量,内存分配了一块区域给x,大小为4字节,假设是0Xffff1。然后x的值是0.
对于int* p = &x;,p是一个指针变量,内存分配了一块区域给p,大小为4字节(32位电脑上),假设是0Xffff2。然后它的初值指向x的地址,也就是p的值是0Xffff1。
对于int& r = x;,r是一个引用变量,内存分配了一块区域给r。r是引用的x,可以理解成r代表了x,他俩是一个东西。由于x是整数内存为4字节,所以r分配的内存大小也为4字节,假设是0Xffff3。r的值也就是x的值,是0。
引用一定要有初值,且设完后不能改变!否则编译器报错
sizeof(r) == sizeof(x)
&x == &r 特别注意,虽然r有另外分配内存,但&r是和&x相等的,都是0Xffff1。
对于int x2 = 5,x2是一个整数变量,内存分配了一块区域给x2,大小为4字节,假设是0Xffff4。然后x的值是5.
- 第二次
继续看下面代码
r = x2;
int& r2 = r;
对于r = x2;,由于r是个引用,且它的初值已经赋了x。我们又强调了引用定义后不能更改。所以这句话的意思并不是把r的引用变成了x2,而是把x2的值赋给r。由于r是x的引用,所以此时r=5 且 x=5。我们可以理解成,引用就是一个别名!一定引用后就不能重新引用了!
对于int& r2 = r;,r2是一个引用变量,r2代表r,r代表了x,所以它们仨是同一个东西。同时,内存也给r2分配了一块区域,大小为4字节。此时r2的值是5.
常见用途
reference通常不用于声明变量,而用于参数类型和返回类型的描述
void func1(Cls* pobj) { pobj->xxx(); } // 被调用端写法不同,不好
void func2(Cls obj) { obj.xxx(); } // 被调用端写法相同,很好
void func3(Cls& obj) { obj.xxx(); } // 被调用端写法相同,很好
...
Cls obj;
func1(&obj); // 接口不同,困扰
func2(obj); // 调用接口相同
func3(obj); // 调用接口相同
以下被视为“same signature”,所以不能共存
double imag(const double& im) {...}
double imag(const double im) {...} // ambiguity