zoukankan      html  css  js  c++  java
  • c++引用深入探讨

    (偶然翻起自己的旧博,忽然发现大三的时候写的这篇文章,仔细看看觉得写的还是那么回事,所以赶紧搭救出来)

    引用的声明:   基本格式:引用类型 &引用名=被引用对象 

    1. &运算符:声明运算符& 跟取地址运算符&和位异或运算符&没有任何关系
    2. extern关键字:一般情况下 引用的声明必须指定被引用对象 唯一的例外是使用extern关键字
    3. const关键字:一般情况下 被引用对象必须是有效的左值对象 但是const关键字修饰的常引用类型允许被引用对象不是左值对象

    引用的使用:引用可以被当作被引用对象的别名使用,单纯的引用是无意义的,引用主要应用于四个方面:

    1. 函数参数:可修改的实参,高效的复杂对象传递方式
    2. 函数返回值:不产生复制的返回值,返回左值类型的函数
    3. 运算符重载:为++ -- << >>等运算符提供了更贴近原意的重载方式
    4. 多态:代替指针使用,实现抽象类的引用

     引用的深入探讨:现在开始进入正题

        1.引用占内存空间吗?

            如果引用只是一个别名的话 他不应该占有内存空间 我用下面这段代码来查看

     

    复制代码
    代码
    #include <iostream>
    using namespace std;
    void fa(){
        
    int a[4];    
        cout
    <<a<<endl;
    }
    void fb(){
        
    int a[4];
        
    int &b=a[0];
        cout
    <<a<<endl;
        fa();
    }
    void fc(){
        
    int a[4];
        cout
    <<a<<endl;
        fb();
    }
    int main()
    {
        fc();
        getchar();
        
    return 0;
    }
    复制代码

     

     

    这段代码里 我用了三个嵌套的函数调用 这样 fa 和fc的栈段就把fb夹在了中间 fb的栈段大小变化的话 会导致fc中a的地址偏移 但是并不是每个分配都会导致栈段增大的 所以应该先测试一下 确定a的合适大小 使得一旦声明变量 b的栈段就增大。

    int &b=a[0];注释掉的话 可以看到fc中输出的地址变了 fb没有变 那么 引用b显然占据了内存空间 我的代码在g++中编译,结果也是g++的结果。

    2.引用的值不可改变吗?

    一个已经初始化的引用类型对象 其引用的对象不可能被合法的改变。

    前面一段代码展示给我们 引用确实占据了内存空间 ,了进一步了解其本质,我们必须获得它的地址。&取地址操作符显然是无法做到的 几乎每个学c++的人都会尝试用这种办法去取引用类型的地址,但得到的都是被引用对象的地址。

    还从前面的例子入手 fb中 a的地址没有改变  fa中a的地址改变 那么 int &b的分配应该在 二者之间 于是 最可能的位置就是a中的a[4]   但输出之后我发现a[4]不是,因为数组a是跟栈逆向分配的 之后我试了这样的代码
    void fb(){
        int a[4];
        int b=20;
        cout<<a[-1]<<endl;
        fa();
    }

     在我的编译器中 b跟a[-1]总是相等 于是 我把int b 替换成int &b=a[0]; ok 我发现它指向了一个貌似地址的东西。改变b的指向 发现a[-1]是随之变化的 现在 我几乎可以确定 a[-1]就是b了 再用一段这样的代码来检验
    void fb(){
        int a[4]={1,2,3,4};
        int &b=a[0];
        a[-1]+=4;
        cout<<b<<","<<a[0]<<endl;
        fa();
    }

    引用真的是不可改变的吗? 在这个例子中 我使b指向了a[1] 而不再是a[0]

    3.引用和指针
    从上面的例子看出 引用的内部实现和指针并无两样。如果参考其他语言的思想的话 可以得到结论:引用就是指针常量。 在c++中 引用在语法上与指针有着明显的差异 但是 他们并没有本质不同 引用是c++中实现的一种限制比较严格的常量指针 它在参与任何运算之前自动解引用。

    在使用中 推荐尽量用引用代替指针,因为引用是一种比指针更安全的类型 并且有更清晰的语义(当然指针也有适合的语义)

    4.其他语言
    顺便一提,在C家的其他语言中 引用几乎被作为访问对象的唯一手段

    C++:有指针 所有运算符会解引用 所有对象不作为引用 传递参数和返回值时如果不希望复制 则必须将形参指定为引用类型
    C#: unsafe模式有指针 除了=之外的操作符会解引用 所有对象作为引用 传递参数和返回值时如果希望复制 则必须显式clone
    Java:无指针 除了=之外的操作符会解引用 类似c#
    javascript:无指针但是可以变通 除了=之外的操作符会解引用 没有提供复制传递的方法(郁闷)

    Keep it simple!
    作者:N3verL4nd
    知识共享,欢迎转载。
  • 相关阅读:
    hdu 5101 Select
    hdu 5100 Chessboard
    cf B. I.O.U.
    cf C. Inna and Dima
    cf B. Inna and Nine
    cf C. Counting Kangaroos is Fun
    Radar Installation 贪心
    spfa模板
    Sequence
    棋盘问题
  • 原文地址:https://www.cnblogs.com/lgh1992314/p/5834793.html
Copyright © 2011-2022 走看看