请帮忙理解以下引用,并指出和指针的区别!谢谢参与!

解决方案 »

  1.   

    引用不能等同于指针,他是某个变量的别名。他并不新分配内存,但指针仍旧分配4字节内存,此地址里的内容是其所指向变量的地址。
    可作如下测试:
    int a = 1;
    int &b = a;
    int *c = &a; printf("0x%lx\n", &a);
    printf("0x%lx\n", &b);
    printf("0x%lx\n", &c);
      

  2.   

    1. 引用 cannot be null in C++.
    2. 引用 does not have pointer arithmetic.
    with pointer, int* p=&i; p++;
    but with 引用, no way to do that.3. 引用 may use memory.
    void f(int& ri){......}
      

  3.   

    to duiduiblues(duiduiblues):
    >他并不新分配内存,...可是用VC可看到:
    2:        int a=1;
    0040B478   mov         dword ptr [ebp-4],1
    3:        int &b=a;    
    0040B47F   lea         eax,[ebp-4]
    0040B482   mov         dword ptr [ebp-8],eax  ;还是给这个引用分配了内存吧?//====================to fibbery (飞)  :
    小弟比较愚笨,引用看不懂,就看汇编代码,还是觉得汇编明白些(也许因为这样我才一直没什么进步).发现用引用和指针编译后的代码是一样的,都是一个指向变量的地址而已,但是在C++里面就有许多规定,老是记不住,不爽.下面是俺D学习笔记,供参考.有错误别怪我,我实在是很菜,郁闷 :(
    //======================================C++个人学习笔记C++中有些概念很难理解,但是从汇编级看,不管由什么语言编译的都没区别,所以我觉得难懂的地方就看它生成的汇编程序,借以了解其实现细节.但这对了解"面向对象"的思想没有帮助,而"面向对象"才是C++的精髓啊,我是舍本求末了.请前辈指教.
    汇编代码是用BC3.1编译来的学习笔记-看汇编学引用(by furydied,2002)要点:
    1.引用和指针都是取地址
    2.指向指针的引用(指向引用的指针是错误的!!!!!)int *&r=p
    3.指向常量的引用int &r=const int MAX
    4.动态分配的引用(new/delete &)
    5.引用作为函数参数:int func(int &x)
    6.返回引用的函数(比较难哟)int &func()1.引用和指针都是取地址
       ; int i=100,j=100;
    mov word ptr [bp-2],100 ;定义的2个变量存放位置:[bp-2],[bp-4]
    mov word ptr [bp-4],100
       ; int &refi=i;
    lea ax,word ptr [bp-2] ;所谓引用:就是取该变量的地址
    mov si,ax
       ; int *p=&i;
    lea ax,word ptr [bp-2] ;所谓指针,也是地址,在汇编代码的层次,
    mov di,ax ;和引用没两样
       ; int &refj=j;
    lea ax,word ptr [bp-4] ;取地址
    mov word ptr [bp-6],ax ;寄存器不够用,就保存到内存中[bp-6]
       ; int *q=&j;
    lea ax,word ptr [bp-4] ;同上
    mov word ptr [bp-8],ax
       ; refi+=100;
    add word ptr [si],100
       ; *p-=100;
    sub word ptr [di],100
       ; cout<<endl<<"refi="<<refi;
    push word ptr [si] ;使用"引用"时也和使用"指针"一样
      ... ;从右至左将<<右边的内容入栈
    call near ptr ostream ;然后调用若干次输出库函数
    add sp,4 ;调整堆栈指针
    ...
    call near ptr ostream
    add sp,4
       ; cout<<endl<<"(*p)="<<*p;
    push word ptr [di] ;对指针的处理完全一样
    ...
    call near ptr @@ostream@$blsh$qpqr7ostream$r7ostream
    add sp,4
    ... ;到目前为止,从汇编代码看来,引用跟指针没什么区别啊!
    ;注意:写程序的时候,
    ;引用是直接将变量赋给引用(int &refi=i),
    ;  ~~~~ ~~
    ;而指针是将变量的地址赋给指针(int *p=&i,多了一个&)
    ;    ~~~~~~~~~~                ~~~
    ;继续:2.指向指针的引用(指向引用的指针是错误的!!!!!)
    ; int i=100,j=100;
    mov word ptr [bp-2],100
    mov word ptr [bp-4],100
       ; int &refi=i; //declare a reference to an integer
    lea ax,word ptr [bp-2]
    mov si,ax
       ; int *p=&i; //declare a pointer to an integer
    lea ax,word ptr [bp-2]
    mov word ptr [bp-8],ax //[bp-8]中存放一个指针
       ; int *&refp=p; //declare a reference to a pointer
       ;            ~~ 注意这里的写法:*&表示一个引用!!不能写作&*!!
    lea ax,word ptr [bp-8] //将bp-8(就是指针变量p所在的地址)
    mov word ptr [bp-10],ax //送到一个引用[bp-10]3.指向常量的引用
       ;     const int k=64; //常量
    mov word ptr [bp-6],64
       ; int &refk=k; //指向常量的引用
    mov word ptr [bp-12],64 //生成了一个临时变量[bp-12]
    lea ax,word ptr [bp-12] //并将这个变量的值设为常量的值
    mov di,ax //di->该临时变量
       ;     refk+=64; //改变该引用的值
    add word ptr [di],64 //改变的是临时变量的值,而不是原来定义的常量的值4.动态分配的引用
    float &reff=* new float(66.6); //动态分配引用的话,new 前面要加 * !!
    //new float返回一个指针,所以用*取该指针指向的变量.
    //如果不加*的话,编译错误:Can't convert (float *) to float
    //意即引用&reff被定义为float类型,和float f没区别,
    delete &reff; //如何删除:前面加&5.引用作为函数参数
    #include <iostream.h>
    void swap(int &a,int &b){ //形参为整型引用
    int temp=a;
    a=b;
    b=temp;
    return;
    }
     汇编代码:
    enter 2,0
    push si
    push di
    mov si,word ptr [bp+4] ;x的地址=>si
    mov di,word ptr [bp+6] ;y的地址=>di
       ; int temp=a;
    mov ax,word ptr [si]
    mov word ptr [bp-2],ax ;暂存x([bp-2]为temp)
       ; a=b;
    mov ax,word ptr [di]
    mov word ptr [si],ax ;y=>[x]
       ; b=temp;
    mov ax,word ptr [bp-2] ;暂存的x=>[y]
    mov word ptr [di],ax pop di
    pop si
    leave
    ret int main()
    {
    int x=10,y=20;
    /* 汇编代码:
     * mov word ptr [bp-2],10 ;x
     * mov word ptr [bp-4],20 ;y
     */
    cout << endl << "x=" << x
    << "\ty=" << y;
    swap(x,y); //实参为整型变量
    /* 汇编代码:
     * lea ax,word ptr [bp-4] ;y的地址(而不是变量值!!!)
     * push ax ;push &y(先)
     * lea ax,word ptr [bp-2] ;x的地址(而不是变量值!!!)
     * push ax ;push &x(后)
     * call near ptr @swap$qrit1
     * add sp,4
     */
    cout << endl << "After swapping:"
    << endl << "x=" << x
    << "\ty=" << y;
    return 0;
    }
    从上面可以看到,以引用作为函数参数时,调用函数直接使用整型变量.编译程序找到函数原型,发现这里须要的是一个引用,就将实参的地址(而不是变量值)入栈传给函数.被调用函数中是用传过来的地址运算的.下面用指针实现相同的功能:
    #include <iostream.h>
    void swap(int *a,int *b){
    int temp=*a;
    *a=*b;
    *b=temp;
    return;
    }
    /*这一段的汇编代码:
       ; void swap(int *a,int *b){
    @swap$qpit1 proc near
    enter 2,0
    push si
    push di
    mov si,word ptr [bp+4]
    mov di,word ptr [bp+6]
       ; int temp=*a;
    mov ax,word ptr [si]
    mov word ptr [bp-2],ax
       ; *a=*b;
    mov ax,word ptr [di]
    mov word ptr [si],ax
       ; *b=temp;
    mov ax,word ptr [bp-2]
    mov word ptr [di],ax
       ; return;
    jmp short @1@58
       ; }
    pop di
    pop si
    leave
    ret
    */
    int main()
    {
    int x=10,y=20;
    cout << endl << "x=" << x
    << "\ty=" << y;
    swap(&x,&y);
    /*汇编代码:
     * lea ax,word ptr [bp-4]
     * push ax
     * lea ax,word ptr [bp-2]
     * push ax
     * call near ptr @swap$qpit1
     * add sp,4
     */ cout << endl << "After swapping:"
    << endl << "x=" << x
    << "\ty=" << y;
    return 0;
    }
    可以看到,使用指针与使用引用,生成的汇编代码完全一样,没有分别;有分别的地方只在于C++中声明/调用的形式不同.6.返回引用的函数(比较难哟)
     //返回引用的函数示例
    #include <iostream.h>
    int &func(void){ //在函数名前加一个&,则此函数返回一个引用
    //此引用的类型就是函数名前面声明的类型
    static int count=0;
    return (++count);
    }
    汇编代码:
    inc word ptr DGROUP:d@w+0 ;将变量count加1
    mov ax,offset DGROUP:d@w+0 ;返回变量count的地址
    pop bp
    ret int main(){
    int i;
    cout << endl;
    for ( i=0; i<5; i++) //输出1 2 3 4 5 
    cout << func() << '\t'; //奇怪:这里func()返回一个地址,cout却输出一个变量值?
    //要输出这个地址,还得cout << &func() (前面加&取地址!)
    /*这一句的代码:
     * push 9 ;\t
     * call near ptr @func$qv ;调用自己的函数
     * mov bx,ax ;返回AX为静态变量count的地址
     * push word ptr [bx] ;将count的值入栈
     * 编译程序发现这个函数返回引用,就以返回的值为地址取得变量值
     * push offset DGROUP:_cout
     * call near ptr @@ostream@$blsh$qi ;输出?
     * add sp,4
     * push ax
     * call near ptr @ostream@$blsh$qzc
     * add sp,4
     */
    cout <<endl;
    func()=100; //可以对函数赋值!!
    /*  call near ptr @func$qv
     * mov bx,ax
     * mov word ptr [bx],100
     * 先调用函数,返回ax=变量地址,再对变量赋值100
     * 在call完之后,func()中的静态变量值为6
     */
    for (i=0; i<5; i++)
    cout << func() << '\t'; //输出101 102 103 104 105
    return 0;
    }
    再看:将该函数的&去掉,令它不再返回引用
    #include <iostream.h>
    int func(void){
    static int count=0;
    return (++count);
    }
    /* inc word ptr DGROUP:d@w+0
     * mov ax,word ptr DGROUP:d@w+0 ;直接返回变量值
     * pop bp
     * ret
     */int main()
    {
    int i; cout << endl;
    for ( i=0; i<5; i++)
    cout << func() << '\t';
    /* push 9
     * call near ptr @func$qv ;由于函数定义为整型
     * push ax ;所以返回值(变量值)不再是地址
     * push offset DGROUP:_cout
     * call near ptr @@ostream@$blsh$qi
     * add sp,4
     * push ax
     * call near ptr @ostream@$blsh$qzc
     * add sp,4
     */
    cout <<endl; //func()=100; //这一句现在不行啦 for (i=0; i<5; i++)
    cout << func() << '\t'; return 0;
    }
    再看:改成指针类型:
    #include <iostream.h>
    int *func(void){ //在函数名前加一个&,则此函数返回一个引用
      

  4.   

    引用可以看作更安全、方便的指针。引用肯定指向了对象,不必是否空指针,引用也不用*,写起来简洁。从fury的分析中就可以知道,引用和指针的内部处理其实基本是一样的。
    按书上的说法,引用是为了支持运算符的重载而引入的:)