const int f[10] = { 1,2,3,4,5,6,7,8,9,10 };

int main()
{
// test1
const int i = 3;
int& j = const_cast<int&>(i); // 使用const_cast关键字进行强制类型转换 j = 5;
// 这俩值 会一样吗 ?
cout << "i = " << i << endl;
cout << "j = " << j << endl; // 这俩地址 会一样吗 ?
cout << "&i = " << &i << endl;
cout << "&j = " << &j << endl;
// 实验小结:打印的i和j的地址一样,但是i和j的值却不一样,说明什么?
// 一个内存单元上不可能有两个不同的值!这里肯定涉及到两个内存单元,而不是一个!即编译器内部做了手脚。
// 结论:这个最复杂,直接看最后的结论。 // test2 探究 --- 对引用取地址
int y = 89;
int& x = y;
// 这俩地址 会一样吗 ?
cout << "&x = " << &x << endl;
cout << "&y = " << &y << endl;
// 答: 当然一样 。 因为引用就是别名而已,对同一个内存空间的别名。 // test3
//test3 - PART1 本步骤证明了z是只读变量,因为可以通过其地址修改其值
const int& z = 99;
int* p = const_cast<int*> (&z);
*p = 88;
cout << "z = " << z << endl; // test3 - PART2 本步骤证明了上面定义的i不是只读变量,而是常量。
int* p1 = const_cast<int*> (&i);
*p1 = 88;
cout << "i = "<< i << endl; /*
个人小结:
1:对常量使用extern关键字或者是&操作符时,内存中会新生成一份该常量对应的变量。
2:引用,是对某个内存空间冠以别名,对应的就是变量,变量才占有内存空间。而常量存储在符号表内,是没有地址的。
3:当对引用取地址,取到的地址是某个内存空间的地址。
4:引用的本质是别名,如果此时已经存在了内存空间,那么之后的所有引用都只是该内存空间的别名,并不会涉及到内存空间的分配。 */ // test4 -- 补充实验
const int s[10] = {1,2,3,4,5,6,7,8,9,10};
int& s1 = const_cast<int&>(s[0]); s1 = 5;
cout << "s[0] = " << s[0] << endl;
cout << "s1 = " << s1 << endl;
// 实测,这里的数组值可以被修改。看test5. 是推导出下面结论的步骤细节。
// 先爆结论:
// const修饰栈上的数组,其数组元素是只读变量,而const修饰全局数据区的数组,其数组元素是常量。 // test5 --- 对test4的结果不解,竟然能够修改const数组的元素值! 于是进行本test5,做增补实验。 // test5 - PART1
#if 1
const int f[10] = { 1,2,3,4,5,6,7,8,9,10 }; // 下面使用指针或引用两种方法来测试,二选一即可。 #if 1 // 使用指针来修改值
int* pf = (int*)&f[0];
*pf = 5;
cout << "*pf = " << *pf << endl;
// 实测,值还是被修改了, #else // 使用引用来修改值
int& f1 = (int&)f[0]; f1 = 5;
cout << "f[0] = " << f[0] << endl;
cout << "f1 = " << f1 << endl;
// 实测,值还是被修改了, #endif // 结论: 这里的const数组元素不是常量,是只读变量。 // 提出疑惑:这里代码展示的const修饰数组,得不到常量数组元素???为什么呢? 继续实验, 继续向下看: #else // test5 - PART2 int& f1 = (int)f[0]; // 修改代码,这里使用了全局数组const int f[10] #if 1
f1 = 5; // 实测,运行期执行本条语句时发生异常,程序奔溃,提示写入访问权限冲突。
#else
f[0] = 8; // 对const修饰的全局数组元素赋值,编译器也会报错。
#endif cout << "f[0] = " << f[0] << endl;
cout << "f1 = " << f1 << endl; // 结论: 根据编译期的报错提示 和运行期的程序异常时提示的“写入访问权限冲突”,
// 我们可以得出: const修饰全局数据区的数组,其数组元素是常量。
// C++里const修饰的数组和其存储区有关系!
// 而之前 test5 - PART1 之所以得到只读数组元素,是因为const修饰的数组存储区域在栈上。 #endif // test 6 . 深究const_cast,对const_cast的使用进行打擦边球
#if 1
// tes6 -- PART1
// 百度百科的解释:
/*
const_cast,其主要作用是:修改类型的const或volatile属性。使用该运算方法可以返回一个指向非常量的指针(或引用)指向b1,就可以通过该指针(或引用)对它的数据成员任意改变。
*/
//对const_cast的基本使用在test4内已经有演示, // !我们这里对const_cast的实验进行打擦边球: 不传入只读变量,传入常量。! const int const_var = 3; // 千万注意,这里的const_var变量虽然也是在main函数内部定义,但是不要觉得这是栈变量,这是常量,新手学习C++时,这是最基本的例子。
// 不要把我上述讨论的const修饰的栈数组,和这里const修饰的单个变量搞混淆,要区分开。
// 否则,看完我的文章,连基本的使用C++的const定义一个常量都不会了,那不是技术退步了。 int& ref_const_var = const_cast<int&>(const_var);
// 实测编译没报错。
// 结论:
// 参见上述个人小结,第一条小结:
//1:对常量使用extern关键字或者是 & 操作符时,内存中会新生成一份该常量对应的变量。 // 这个实验相当于又把本文test1的实验重新做了一遍,但是这次加深了理解。 #else
// const_cast的正确打开方式, 不给实验了,直接写中文 // const_cast的常用场景:
// 因为不能把一个const只读变量直接赋给一个非const变量,必须要使用const_cast进行转换,才能避免编译器报错。 // const_cast的冷门场景:
// 即上述打擦边球的场景,遇到这种场景,重在理解,参见tes6 -- PART1 ,或者, 上述个人小结的第一条小结。 #endif return 0;
}

个人小结:
<1>
1:对常量使用extern关键字或者是&操作符时,内存中会新生成一份该常量对应的变量。
2:引用,是对某个内存空间冠以别名,对应的就是变量,变量才占有内存空间。而常量存储在符号表内,是没有地址的。
3:当对引用取地址,取到的地址是某个内存空间的地址。
4:引用的本质是别名,如果此时已经存在了内存空间,那么之后的所有引用都只是该内存空间的别名,并不会涉及到内存空间的分配。
<2>
const修饰栈上的数组,其数组元素是只读变量,而const修饰全局数据区的数组,其数组元素是常量。
<3>
const_cast的常用场景:
因为不能把一个const只读变量直接赋给一个非const变量, 有时候却有这种赋值需求,那就必须要使用const_cast进行转换,避免编译器报错。


最后语: C语言里的const修饰的都是只读变量,但是C++的const完全和C的意义不同,因为C++里存在真正的常量。所以需要重新学习。
本实验阐释了部分C++引用、对引用取地址、const、全局const数组、局部const数组等特性和相关涉及,但尚不完整。
以const关键字为例,const还可以修饰类对象、成员函数等,也有相关注意事项,本文均未作展示。


.

深入C++引用及其注意事项、对引用取地址时的内存模型、const数组等的更多相关文章

  1. Android之线程安全的单例模式,Adapter注意事项之引用传值

    线程安全的单例模式单位模式一般写法如下: public static FestivalLab mInstance; private FestivalLab() { } public static Fe ...

  2. php中引用&的真正理解-变量引用、函数引用、对象引用

    php的引用(就是在变量或者函数.对象等前面加上&符号) //最重要就是 删除引用的变量 ,只是引用的变量访问不了,但是内容并没有销毁 在PHP 中引用的意思是:不同的名字访问同一个变量内容. ...

  3. spring jpa 实体互相引用返回restful数据循环引用报错的问题

    spring jpa 实体互相引用返回restful数据循环引用报错的问题 Java实体里两个对象有关联关系,互相引用,比如,在一对多的关联关系里 Problem对象,引用了标签列表ProblemLa ...

  4. final修饰的变量是引用不能改变,还是引用的对象不能改变???

    对于这个问题,我们不能只记结论,要拿实例说话,参看以下代码: public class Demo { public static void main(String[] args) { final St ...

  5. [转载]& 引用 取地址

    原文地址:& 引用 取地址作者:beter 引用实际上就是给同一个变量取了多个名字.     举个例子:     有个人的名字叫a,之后又改名叫b,这时a和b都是指这个人,这样b就引用了a,即 ...

  6. PHP引用(&)初探:函数的引用返回

    函数的引用返回 先看代码: <?php function &test() { static $b=0;//申明一个静态变量 $b=$b+1; echo $b; return $b; } ...

  7. 详解C++中指针(*)、取地址(&)、解引用(*)与引用(&)的区别 (完整代码)

    一.初步了解--指针与取地址 先看程序: #include<cstdio> int main(void) { int num = 7; int *p = &num; printf( ...

  8. [转载]C++中 引用&与取地址&的区别

    一个是用来传值的 一个是用来获取首地址的 &(引用)==>出现在变量声明语句中位于变量左边时,表示声明的是引用.     例如: int &rf; // 声明一个int型的引用r ...

  9. C++中 引用&与取地址&的区别

    微信公众号[程序员江湖] 作者黄小斜,斜杠青年,某985硕士,阿里 Java 研发工程师,于 2018 年秋招拿到 BAT 头条.网易.滴滴等 8 个大厂 offer,目前致力于分享这几年的学习经验. ...

  10. 错误 3 未找到类型“sdk:Label”。请确保不缺少程序集引用并且已生成所有引用的程序集。

    错误: 错误 3 未找到类型“sdk:Label”.请确保不缺少程序集引用并且已生成所有引用的程序集. 错误 1 命名空间“http://schemas.microsoft.com/winfx/200 ...

随机推荐

  1. [oeasy]python0009 - 设置断点_break_point

    ​ 调试程序 回忆上次内容 ​py​​ 的程序是按照顺序执行的 是一行行挨排解释执行的 程序并不是数量越多越好 kpi也在不断演化 ​ 编辑 写的代码越多 出现的bug就越多 那什么是bug呢? 如何 ...

  2. AT_abc178_d 题解

    洛谷链接&Atcoder 链接 本篇题解为此题较简单做法及较少码量,并且码风优良,请放心阅读. 题目简述 给定一个正整数 \(S\),问有多少个数满足以下条件: 序列中必须为 \(\ge 3\ ...

  3. 深入探究 Golang 反射:功能与原理及应用

    Hi 亲爱的朋友们,我是 k 哥.今天,咱们来一同探讨下 Golang 反射. Go 出于通用性的考量,提供了反射这一功能.借助反射功能,我们可以实现通用性更强的函数,传入任意的参数,在函数内通过反射 ...

  4. emojiCTF2024

    emojiCTF2024 WEB http 题目:​​ 思路: 修改 UA 头为 EMOJI_CTF_User_Agent_v1.0:User-Agent: EMOJI_CTF_User_Agent_ ...

  5. 我出一道面试题,看看你能拿 3k 还是 30k!

    大家好,我是程序员鱼皮.欢迎屏幕前的各位来到今天的模拟面试现场,接下来我会出一道经典的后端面试题,你只需要进行 4 个简单的选择,就能判断出来你的水平是新手(3k).初级(10k).中级(15k)还是 ...

  6. 《最新出炉》系列初窥篇-Python+Playwright自动化测试-60 - 判断元素是否显示 - 下篇

    1.简介 有些页面元素的生命周期如同流星一闪,昙花一现.我们也不知道这个元素在没在页面中出现过,为了捕获这一美好瞬间,让其成为永恒.我们就来判断元素是否显示出现过. 在操作元素之前,可以先判断元素的状 ...

  7. 【WebSocket】一个简单的前后端交互Demo

    WebSocket资料参考: https://www.jianshu.com/p/d79bf8174196 使用SpringBoot整合参考: https://blog.csdn.net/KeepSt ...

  8. 【Dos-BatchPrograming】01

    --0. 1.文件后缀的延申 官方教程更推荐使用.cmd作为后缀 .cmd和.bat的区别: http://www.360doc.com/content/12/0810/09/3688062_2293 ...

  9. Human-centric Computing and Information Sciences期刊基本信息

    letpub 地址: https://www.letpub.com.cn/index.php?page=journalapp&view=detail&journalid=10450&a ...

  10. Jax框架在不同版本间的随机数生成并不一致 —— jax.random

    官方: https://jax.readthedocs.io/en/latest/api_compatibility.html#numerics-and-randomness 具体的解释就是在不同的J ...