C++ 中的 const、引用和指针的深入分析

C++中const与引用的深入解析
本文深入探讨了C++中const和引用的相关知识。介绍了const何时为只读变量、何时为常量的判别准则,分析了const引用类型与初始化变量类型的关系。还阐述了指针和引用的区别,从使用和编译器角度分析引用,最后通过编程实验进行验证,为C++开发提供参考。

1,关于 const 的疑问:

    1,const 什么时候为只读变量,什么时候是常量;

       1,const 从 C 到 C++ 进化的过程中得到了升级,const 在 C++ 中不仅仅像在 C 中声明一个只读变量,其在 C++ 中完全可以得到一个常量;

 

2,const 常量的判别准则:

    1,只有用字面量初始化的 const 常量才会进入符号表;

       1,这里是字面量初始化 const 常量,不是 const 常引用;

       2,得到了真正意义上的常量;

    2,使用其他变量初始化的 const 常量仍然是只读变量;

       1,编译器在编译期间不可能知道变量初始化时候的值;

       2,得到只读变量;

    3,被 volatile 修饰的 const 常量不会进入符号表;

       1,volatile 表示声明的标识符是易变的;

       2,这个可能的易变性也许不在当前编译的文件中,发生在外部;

       3,外部相当于在其它文件中,比如多线程、中断等;

       4,每次访问 volatile 修饰的标识符时,因为是易变的,所以应该到内存中直接读取;

       5,意味着被 volatile 修饰的标识符不可能进入符号表;

       6,意味着当 volatile 和 const 同时修饰一个标识符时,得到的是只读变量,不可能进入符号表;

       7,const 此时的意义说明在当前的文件或者当前的作用域当中,volatile 和 const 一起修饰的标识符不能出现在赋值符号的左边;

 (4),在编译期间不能直接确定初始值的 const 标识符,都被作为只读变量处理;

 

3,const 引用的类型与初始化变量的类型:

    1,相同:初始化变量成为只读变量;

    2,不同:生成一个新的只读变量;

 

4,const 典型问题分析编程实验:

    1,main.cpp 文件:

 1 #include <stdio.h>
 2 
 3 int main()
 4 {
 5     const int x = 1;//直接得到值,进入符号表,但是还是会为 x 分配空间,只不过这个空间 x 没有用而已;
 6     const int& rx = x;//rx代表只读变量,这个变量是编译器为x分配而没有使用的空间;引用代表变量的别名,而变量代表一段内存空间的别名,所以引用代表一段内存空间的别名;
 7     
 8     int& nrx = const_cast<int&>(rx);  //消除 rx只读属性,和rx 代表的内存空间相同;
 9     
10     nrx = 5;
11     
12     printf("x = %d\n", x);
13     printf("rx = %d\n", rx);
14     printf("nrx = %d\n", nrx);
15     printf("&x = %p\n", &x);
16     printf("&rx = %p\n", &rx);
17     printf("&nrx = %p\n", &nrx);
18     
19     volatile const int y = 2;  // 只读变量;
20     int* p = const_cast<int*>(&y); //y被 const修饰,取到的地址也有 const 属性,这里将地址只读属性去掉;
21     
22     *p = 6;
23     
24     printf("y = %d\n", y);
25     printf("p = %p\n", p);
26     
27     const int z = y;  // y 是变量,得到只读变量;
28     
29     p = const_cast<int*>(&z);
30     
31     *p = 7;
32     
33     printf("z = %d\n", z);
34     printf("p = %p\n", p);
35     
36     char c = 'c';
37     char& rc = c;
38     const int& trc = c;  // char 类型默认转换为 int;const 引用初始化类型不同,将得到新的只读变量,所以改变 rc 和 trc 没有丝毫关系;
39     
40     rc = 'a';
41     
42     printf("c = %c\n", c);
43     printf("rc = %c\n", rc);
44     printf("trc = %c\n", trc);
45     printf("&c = %p\n", &c);
46     printf("&rc = %p\n", &rc);
47     printf("&trc = %p\n", &trc);
48     
49     return 0;
50 }

    2,输出结果:

 1 x = 1  // 进入符号表,编译期间就是 1;
 2 rx = 5
 3 nrx = 5
 4 &x = 0xbfb1a708//为const修饰的标识符分配空间,通过指针或引用使用;
 5 &rx = 0xbfb1a708
 6 &nrx = 0xbfb1a708
 7 y = 6
 8 p = 0xbfb1a6fc
 9 z = 7
10 p = 0xbfb1a6f4
11 c = a
12 rc = a
13 trc = c  // 原始的赋值结果;
14 &c = 0xbfd1242f
15 &rc = 0xbfd1242f
16 &trc = 0xbfd12408  // 新开辟的空间;

 

5,关于引用的疑问:

    1,引用与指针有什么关系,如何理解“引用的本质就是指针常量”;

 

6,指针和引用分析:

    1,指针是一个变量:

       1,值为一个内存地址,不需要初始化,可以保存不同的地址;

       2,通过指针可以访问对应内存地址中的值;

       3,指针可以被 const 修饰成为常量或者只读变量;

    2,引用只是一个变量的新名字:

       1,对引用的操作(赋值,取地址等)都会传递到代表的变量上;

           1,新名字是一段内存空间的代号;

           2,引用是给已经存在的合法内存空间一个新的代号;

       2,const 引用使其代表的变量具有只读属性;

       3,引用必须在定义时初始化,之后无法代表其它变量;

           1,身份证号代表一个人,不能复用;

           2,一个车牌号就代表一个车,不能复用;

           3,因为是指针常量,所以不能代表其它变量;

 

7,从 C++ 不同角度分析引用:

    1,从使用 C++ 语言的角度来看:

       1,引用与指针没有任何的关系;

       2,引用是变量的新名字,操作引用就是操作对应的变量;

    2,从 C++ 编译器的角度来看:

       1,为了支持新概念,“引用”必须要一个有效的解决方案;

       2,在编译器内部,使用指针常量来实现“引用”;

       3,因此“引用”在定义时必须初始化;

 

8,在工程项目开发中:

    1,当进行 C++ 编程时,直接站在使用的角度看待引用,与指针毫无关系,引用就是变量的别名;

    2,当对 C++ 代码进行调试分析时,一些特殊情况,可以考虑站在 C++ 编译器角度看待引用;

    3,下面代码正确吗?

1 int a = 1;
2 int b = 2;
3 int* pc = new int(3);
4 int& array[] = [a, b, *pc];

 

9,引用典型问题分析编程实验:

    1,main.cpp 文件:

 1 #include <stdio.h>
 2 
 3 int a = 1;
 4 
 5 struct SV
 6 {
 7     int& x;
 8     int& y;
 9     int& z;
10 };
11 
12 int main()
13 {
14     int b = 2;
15     int* pc = new int(3);
16     SV sv = {a, b, *pc};  // 结构体中的每个元素是引用就可以;
17     // int& array[] = {a, b, *pc}; //数组中的每个元素是引用就不可以;error: declaration of ‘array’ as array of references; C++ 天生要支持 C 语言,C 语言中数组中的每个元素在内存中是顺序存放的,地址是递增的,所以在 C++ 中也要兼容这个特性,而在 C++ 中唯有引用数组破快了这个特性,所以说 C++ 中不支持引用数组;&array[1] - &array[0] = ?  Expected ==> 4;
18     
19     printf("&sv.x = %p\n", &sv.x);
20     printf("&sv.y = %p\n", &sv.y);
21     printf("&sv.z = %p\n", &sv.z);
22     
23     delete pc;
24     
25     return 0;
26 }

   2,输出结果:

      &sv.x = 0x804a020

   &sv.y = 0xbffe92bc

   &sv.z = 0x9f97008

    3,在开发中遇到奇怪的 bug,要站在编译器的角度考虑问题;

 

10,小结:

    1,指针是一个变量;

    2,引用是一个变量的新名字;

    3,const 引用能够生成新的只读变量;

    4,在编译器内部使用指针常量实现“引用”;

       1,C++ 中为了兼容 C 语言中的所有特性,放弃了引用数组,这样会使得相邻元素的地址之差不是期望的;

    5,编译时不能直接确定初始值的 const 标识符都是只读变量;

转载于:https://www.cnblogs.com/dishengAndziyu/p/10904357.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值