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==003 CF 9 C 4&pi==003 CF 9 ACで2つのdisを隔てて、実は1つのrを挟んだのです