c++之引用的本质

引用变量是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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值