您的位置:首页 > 编程语言 > C语言/C++

c++之引用的本质

2016-04-18 19:34 295 查看
引用变量是c++引入的重要机制。

错误观念:引用本质只是别名,在符号表中ri和i对应于相同的变量地址

int i=5;
0100437E  mov         dword ptr [i],5
int &ri=i;
01004385  lea         eax,[i]
01004388  mov         dword ptr [ri],eax
ri=8;
0100438B  mov         eax,dword ptr [ri]
ri=8;
0100438E  mov         dword ptr [eax],8


在底层实现上,引用是用指针常量实现的,如果用指针常量实现,反汇编是一毛一样的。引用和指针常量关系如下:

(1)内存中占用都是4字节,存放都是被引用对象的地址,都必须在定义的同时进行初始化。

(2)指针常量本身允许寻址;引用变量不允许寻址,&r返回的是被引用对象的地址,就是变量r中的值,而不是变量r的地址,r的地址由编译器掌握,程序猿无法直接对其进行存取。

(3)凡用引用的代码,都可以用指针常量实现;反之不然,因为引用本身限制较多,不能完成指针所有的操作。

例如下面的代码是合法的:

int i=5,j=6;
int *const array[] = {&i,&j}; //指针数组


但是如下代码却是非法的:

int i=5,j=6;
int &array[] = {i,j}; //不可能有引用的数组


虽然引用在初始化时会绑定一个变量,不过也是可以有特殊手段可以改变引用绑定关系:

int main()
{
//freopen("input.txt","r",stdin);\

int i=5,j=6;
int &r = i;
void *pi = &i,*pj = &j;
int* addr;
int dis = (int)pj-(int)pi;
addr = (int *)((int)pj+dis); //精确计算r的地址

cout<<"&i == "; PRINT(pi); //i的地址
cout<<"&j == "; PRINT(pj); //j的地址
cout<<"&pi == "; PRINT(&pi); //pi的地址
cout<<"&pj == "; PRINT(&pj); //pj的地址
cout<<"dis == "; PRINT(dis);
PRINT(*addr);

//(*add)+=dis;
(*addr)=(int)&j; PRINT(*addr); //将r指向j

r=666;
cout<<"i == "; PRINT(i);
cout<<"j == "; PRINT(j);

return 0;
}


答案输出:

&i == 003CF9D0

&j == 003CF9C4

&pi == 003CF9AC

&pj == 003CF9A0

dis == -12

3996112

3996100

i == 5

j == 666

因为在内存中排布方式是:

dis 低地址

addr

pj

pi

r

j

i 高地址



&j == 003CF9C4

&pi == 003CF9AC

中隔了2个dis,其实就是夹了一个r
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: