zoukankan      html  css  js  c++  java
  • C++学习笔记之 引用

    先声明一下,这里的内容大多是《C++编程思想》中的内容,我最近在学习C++,觉得里面的很多话不错,另外例子也都自己实验了一番,有些现象很有趣,希望与大家分享。

    •引用(reference)(&)就像能自动地被编译器间接引用的常量型指针。(常量型指针的含义就是常量修饰指针,即指的地方不变,但所指地方的内容可以改变。)

    #include <iostream>  
    using namespace std;  
    
    int y;
    int& r = y;//当一个引用被创建的时候,它必须被初始化为一个对象。
               //你也可以这样写:
    const int& q = 12;//(1)这时,引用就被绑定到一个存储位置中。
    int x=0;  //(2)   
    int& a =x;//(3)
    
    int main()  
    {  
        cout<<"x = "<<x<<",a = "<<a<<endl;
        a++;
        cout<<"x = "<<x<<",a = "<<a<<endl;
    
        system("pause");
        return 0;  
    }  

    代码运行结果:
    这里写图片描述

    在位置(1),编译器分配了一个存储单元,它的初始值被初始化为12,于是这个引用就和这个存储单元联系上了。应用要点是任何引用必须和存储单元联系。访问引用时,就是访问这个存储单元。因此,增加a事实上就是增加x,这个可在main()函数中显示出来,思考一个引用最简单的方法就是把它当做一个奇特的指针,这个指针的一个优点是不必怀疑它是否被初始化了(编译器强迫它初始化),也不必知道怎样对它间接引用(这由编译器做)。
    使用引用时有一定的规则:

    1.当引用被创建时,它必须被初始化(指针则可以在任何时候被初始化)。
    2.一旦一个引用被初始化为指向一个对象,它就不能改变为另一个对象的引用(指针则可以在任何时候指向另一个对象)。
    3.不可能有NULL引用。必须确保引用是和一块合法的存储单元关联。

    •函数中的引用:
    最经常看见引用的地方是在函数的参数和返回值中。当引用被用作函数参数时,在函数内任何对引用的更改将对函数外的参数产生改变。当然,可以通过传递一个指针来做相同的事情,但引用具有更清晰的语法。
    如果从函数中返回一个引用,必须像从函数中返回一个指针一样对待,当函数返回时,无论引用关联的是什么都应该存在,否则,将不知道指向哪一个内存。

    int& h()
    {
        int q;
        return q;//警告,返回的是局部变量或临时变量的地址
    }

    出现结果:这里写图片描述

    int& h()
    {
        static int x;
        return x;//OK
    }

    这样就没有报错。

    #include <iostream>  
    using namespace std;  
    
    int* f(int* x)
    {
        (*x)++;
        return x;
    }
    
    int& g(int& x)
    {
        x++;
        return x;
    }
    
    int main()  
    {  
        int a=0;
    
        cout<<"f(&a) = "<<f(&a)<<endl;
        cout<<"a = "<<a<<endl;
    
        cout<<"g(a) = "<<g(a)<<endl;
        cout<<"a = "<<a<<endl;
    
        system("pause");
        return 0;  
    }  

    这里写图片描述

    可见f()函数传进去的是a的地址,返回的也是a的地址。
    g()函数传进去的是a的引用,相当于传进去的a的存储单元的值,返回的是a的存储单元的值。
    对函数f()的调用缺乏使用引用的方便性和清晰性,但很清楚这是传递一个地址。在函数g()的调用中,地址通过引用被传递,但表面上看不出来。

    •常量引用
    刚刚函数中参数是非常量对象时,这个引用参数才能工作。如果是常量对象,函数g()将不接受这个参数,这样做是一件好事,因为这个函数将改变外部参数。如果知道这函数不妨碍对象的不变性的话,让这个参数是一个常量引用将允许这个函数在任何情况下使用。这意味着,对于用户定义的类型,该函数只能调用常量成员函数,而且不应当改变任何公共的数据成员。

    这样就已经报错了,因为你改变的是常量指针

    #include <iostream>  
    using namespace std;  
    
    void f(int& x)
    {
        x++;
    }
    
    void g(const int& x)
    {
        x++;
    }
    
    int main()  
    {  
        int a=0;
    
        f(1);
        g(1);
    
        system("pause");
        return 0;  
    }  
    

    这里写图片描述

    调用f(1)会产生编译期间错误,这是因为编译器必须首先建立一个引用,即编译器为一个int类型分派存储单元,同时将其初始化为1并为其产生一个地址和引用捆绑在一起。存储的内容必须是常量,因为改变它没有任何意义,我们再不能对它进行操作。当改变这种数据的时候,编译器会指出错误,这是非常有用的提示,因为这个改变会导致信息丢失。

    •指针引用

    在C语言中,如果想改变指针本身而不是它所指向的内容,函数声明可能像这样:

    void f(int **)

    当传递它时,必须取得指针的地址:

    int i = 47;
    int* ip = &i;
    f(&ip);

    对于C++中的引用,语法清晰多了。函数参数变成指针的引用,用不着取得指针的地址。
    int*& i理解的话,相比于int& i。我的理解是int*& i, i首先是一个引用,之后是对int*的引用,即指针的引用。

    #include <iostream>  
    using namespace std;  
    
    void increment(int*& i)
    {
        i++;
    }
    
    
    int main()  
    {  
        int* i=0;
    
        cout<<"i = "<<i<<endl;
        increment(i);
        cout<<"i = "<<i<<endl;
    
        system("pause");
        return 0;  
    }  

    结果很有意思,定义i是一个指针,指向的地址是0。执行increment(i)函数之后,指针加一,因为是整型变量的指针,指向下一个整型变量,内存地址就加了4。所以结果是:

    这里写图片描述

    有什么说错的地方,还望大家多多指正。

    版权声明:本文为博主原创文章,未经博主允许不得转载。

  • 相关阅读:
    某个牛人做WINDOWS系统文件详解
    常用ASP脚本程序集锦
    LINUX基础:文件安全与权限
    proftpd+mysql+quota
    apache2.0.49tomcat5.0.19jk2建立virtualHost
    URL Redirection(转) Anny
    顶级域名后缀列表(转) Anny
    \u4E00\u9FA5意义 Anny
    How to POST Form Data Using Ruby(转) Anny
    How to get rid of 'Enter password to unlock your login keyring' in Ubuntu(转) Anny
  • 原文地址:https://www.cnblogs.com/lightspeedsmallson/p/4785889.html
Copyright © 2011-2022 走看看