第5课 引用的本质分析

1.  引用的意义

(1)引用作为变量别名而存在,因此在一些场合可以代替指针

(2)引用相对于指针来说,具有更好的可读性实用性

第5课 引用的本质分析 

2. 特殊的引用——const引用

(1)const Type& name = var; //让变量拥有只读属性

(2)当使用常量对const引用进行初始化时,C++编译器会为这个常量值分配空间,并将引用名作为这段空间的别名。但这样用常量对const引用初始化将生成的是一个只读变量。

【实例分析】引用的特殊意义

#include <stdio.h>

void Example()
{
    printf("Example:n");

    int a = 4;
    const int& b = a;//变量a的别名,const让变量b具有只读属性
    int* p = (int*)&b; //&b就是变量a的地址

    //b = 5;//非法,因为用const修饰的引用,其代表的变量是只读的

    *p = 5; //合法,修改变量a的值

    printf("a = %dn", a); //5;
    printf("b = %dn", b); //5
}

void Demo()
{
    printf("Demo:n");

    //const引用
    const int& c = 1; //引用本应是变量的别名。一般,常量是不分配内存的。当编译器看
                      //该行时,会为常量1分配内存,并让b作为这段空间的别名。

    int* p = (int*)&c;

    //c = 5;//非法,因为const修饰,c是只读的

    *p = 5;//合法,通过指针访问内存

    printf("c = %dn", c); //5

    printf("n", c); //5

    //const修饰变量:注意与const引用的区别
    const int a = 1;   
    p = (int*)&a; //遇到&a才为常量分配内存

    //a = 5;//非法,因为const修饰,a是只读的

    *p = 5;//合法,通过指针访问内存

    printf("a = %dn", a); //1,编译器看到a直接从符号表读其值(1)
    printf("*p = %dn",*p); //5
}

int main()
{
    Example();

    printf("n");

    Demo();

    return 0;     
}

3. 引用的本质

(1)引用在C++中的内部实现是一个指针常量,因此引用所占用的空间大小与指针相同。

第5课 引用的本质分析 

(2)从使用的角度,引用只是一个别名,C++为了实用性而隐藏了引用的存储空间这一细节。

  ①在编译过程中,编译器看到int& a的声明就会转换为int* const a;

  ②看到使用引用时,会转为*a,如此隐藏了使用指针的事实

【编程实验】引用的思考

#include <stdio.h>

struct TRef
{
    char& r;//引用的本质是指针常量,因此会分配4字节的空间,相当于char* const r;
};



int main()
{
    char c = 'c';
    char& rc = c;
    TRef ref = {c};

    printf("sizeof(char&) = %dn",sizeof(char&));//1,char型变量别名,大小为1
    printf("sizeof(rc) = %dn",sizeof(rc));      //1,变量c的别名,大小为1

    printf("sizeof(TRef) = %dn",sizeof(TRef));  //结构体内有个引用,本质为指针,占4字节
    printf("sizeof(ref.r)= %dn",sizeof(ref.r)); //1,char型变量的别名,大小为1


    return 0;     
}

【编程实验】引用的存储空间

#include <stdio.h>

struct TRef
{
    char* before; //4字节
    char& ref;//4字节,本质是指针常量,会分配4字节的空间,相当于char* const ref;
    char* after;//4字节
    
};



int main()
{
    char a = 'a';
    char& b = a;
    char c ='c';

    TRef r = {&a, b, &c};

    printf("sizeof(r) = %dn", sizeof(r));               //12
    printf("sizeof(r.before) = %dn", sizeof(r.before)); //4
    printf("sizeof(r.after)  = %dn", sizeof(r.after));  //4
    printf("&r.before = %pn", &r.before);
    printf("&r.after  = %pn", &r.after); //after和before相差8个字节,中间隔了个b引用所占用的空间

    return 0;     
}

4. 引用的意义

(1)功能性:引用在大多数情况下代替指针,可以满足需要使用指针的场合

(2)安全性:可以避开由于指针操作不当而带来的内存错误

(3)操作性:简单易用,又不失功能强大

【实例分析】函数返回引用

#include <stdio.h>

int& demo()
{
    int d = 0;

    printf("demo: d = %dn", d); //输出0

    return d;//返回局部变量的引用,危险
}

int& func()
{
    static int s = 0;
    printf("func: s = %dn", s);//输出0

    return s; //合法,返回的是静态局部变量(位于全局存储区中的)
}



int main()
{
    int& rd = demo();
    int& rs = func();

    printf("n");
    printf("main: rd = %dn", rd);//垃圾数值
    printf("main: rs = %dn", rs);//0,返回全局存储区中的s
    printf("n");

    return 0;     
}

5. 小结

(1)引用作为变量别名而存在,旨在代替指针

(2)const引用可以使得变量具有只读属性

(3)引用在编译器内部使用指针常量实现,其最终本质为指针

(4)引用可以尽可能的避开内存错误

原文链接: https://www.cnblogs.com/5iedu/p/5367317.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍;

也有高质量的技术群,里面有嵌入式、搜广推等BAT大佬

    第5课 引用的本质分析

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/394484

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年4月3日 下午3:47
下一篇 2023年4月3日 下午3:47

相关推荐