📣🥳🥳🥳📣
✨Hello! 如果这篇【文章】对你有帮助😄,希望可以给博主点个赞👍鼓励一下😘
📣🥳🥳🥳📣
🌏目录
🤔 1.指向常量的引用
🏷️ 场景需求
▶️ 程序里有一个对象r
(C++里对象即变量,可以理解为同义词),现在我想设置一个【引用】来【绑定】它,但有一个要求:不能【通过这个引用】来【修改】这个对象的值,但允许通过这个引用来【读取】这个对象。
📝 对于这个场景,C++11标准下这样来实现
int r = 1;
const int &R = r; //引用R绑定了r
cout << R; //正确:允许通过引用R读取r的值
R = 2; //错误:终端提示“ assignment of read-only reference 'R' ”
这个特殊的引用R
应该叫个什么拉风的名字(术语)比较好呢?
✅ 《C++ primer 5th》称其指向常量的引用(reference to const)
,又称常量引用
。
🏷️ 具体分析
上述代码中const int &R = r
的图解如下👇
👇 第五版中文版P55对引用有如下补充介绍
引用的类型必须与其所引用对象的类型一致,但是有两种例外。第一种例外情况就是在初始化
常量引用
(指向常量的引用
)时允许【用任意表达式作为初始值】,只要【该表达式的结果】能【类型转换】(P32节2.1.2)成【引用的类型】即可。
可能有人会问第二种例外情况是什么,我也想知道,但书上作者好像没写🤣,如果有人知道可以在评论区里分享一下。谢谢啦!
👇例子说明
const int m = 1;
int &M = m; //错误:普通的int&不能绑定到int整型常量上(反证法:如果可以,那通过M就能修改m的值,这样就和m是常量的规定发生冲突)
int r = 2;
const int &R = r; //这就是上面的例子。等号右侧的表达式`r`其类型是`int整型`,可以转换成`int整型常量`,因此不会报错
const int &x = 10; //等号右侧的表达式`10`其类型为`整型字面值常量`,可以转换成`int整型常量`
const int &y = r*2+3; //等号右侧表达式的计算结果同样为`整型字面值常量`
此外,对于下面这种情况,仍然成立
double pi = 3.14;
const int &PI = pi;
右侧表达式pi
的类型为double类型
,可以经类型转换成为int整型常量
。那这样的话PI
和pi
的值不就不同了吗?没错,这二者的值确实不同,打印发现pi
为3.14,PI
为3。这和一个新概念有关——临时量(temporary)对象
,简称临时量
。图解如下👇
📌 最后,在分析概念指向常量的指针
之前,补充两概念——底层const
&顶层const
底层const
的定义:若【通过】某【指针/引用】无法对所【指向/绑定】的对象进行【值修改】,我们就称该【指针/引用】为一个底层const
因此上面所有例子中的 `指向常量的指针` 都是 `底层const`
顶层const
的定义:若对象【自身是一个常量】,不可变,则自身就是顶层const
const int x = 1; //x就是一个顶层const
🤔 2.指向常量的指针
🏷️ 场景需求
▶️ 程序里有一个对象r
,现在我想设置一个【指针】来【指向】它,但有一个要求:不能【通过这个指针】来【修改】这个对象的值,但允许通过这个指针来【读取】这个对象。
📝 对于这个场景,C++11标准下这样来实现
int r = 1;
const int *p = &r; //指针p指向了r
cout << *p; //正确:允许通过指针p读取r的值
*p = 2; //错误:终端提示“ assignment of read-only location '* p' ”
这个特殊的指针p
应该叫个什么拉风的名字(术语)比较好呢?
✅ 《C++ primer 5th》称其指向常量的指针(pointer to const)
。但与前面介绍指向常量的引用
不同的是,指向常量的指针
不能称为常量指针
。常量指针
是另外一个术语的名字。
🏷️ 具体分析
上述代码中const int &p = &r
的图解如下👇
👇 第五版中文版P56对指针有如下介绍
指针的类型必须与其所指对象的类型一致,例如,
int类型指针
必须指向int类型
。但是有两种例外。第一种例外情况是允许令一个指向常量的指针
指向一个【非常量对象】,没有规定指向常量的指针
其必须要指向一个常量
。
与指向常量的引用
类似,我们同样无法通过这种特殊指针来修改其所指向的对象的值,因此也是一个底层const
。
👇例子说明
const int r = 1;
int R = 10;
const int *p = &r; //正确:r是一个常量,`指向常量的指针` 理应可以指向一个 `常量`
const int *p1 = &R; //正确:r是一个非常亮,但 `指向常量的指针` 可以指向一个 `非常量对象`
const int *p2 = 10; //错误:没有允许 `指向常量的指针` 可以指向一个 `字面值常量`
🤔 3.常量指针
🏷️ 场景需求
▶️ 程序里有一个对象r
,现在我想设置一个【指针/引用】来【指向/绑定】它,但有一个要求:可以【通过这个指针/引用】来【读取和修改】这个对象的值,但不允许这个指针/引用【移情别恋】其它对象。这里解释下“移情别恋”,对于指针p
,要求它不能再更改指向,即不能再指向其它对象;而对于引用R
,要求它不能再更改绑定,即不能再绑定其他对象【然而这本身就是引用的默认要求!可以见另一篇文章【C++】为何引入“引用“? 指针和引用有何区别?,因此这个并不算特殊的引用,这就是基本的引用。所以下面重点考虑这个特殊指针的语法】。
📝 对于这个场景,C++11标准下这样来实现
int x = 1, y = 10;
int *const p = &x; //指针p指向了x
*p = 2; //正确:允许通过指针p读取和修改x的值
p = &y; //错误:终端提示“ assignment of read-only variable 'p' ”
这个特殊的变量p
应该叫个什么拉风的名字(术语)比较好呢?
✅ 《C++ primer 5th》称其常量指针(const pointer)
。
🏷️ 具体分析
上述代码中int *const p = &x
的图解如下👇
👇 弄清楚下面这些声明的含义
int x = 1;
int *const p = &x;
const int y = 1;
const int *const pp = &y;
“当声明符较多时最行之有效的办法就是从右往左阅读。”
1️⃣ 对于int *const p
,首先是const
,说明p
自身是一个常量,然后是*
,说明p
是一个指针,最后是int
,说明p
是一个指向int整型
的常量指针
,因此等号右侧理应是一个int整型
对象的地址,合理。
2️⃣ 对于const int *const pp
,首先是const
,说明pp
自身是一个常量,然后是*
,说明pp
是一个指针,然后是int
,说明pp
是一个指向int整型
的常量指针
,最后是const
,说明pp
是一个指向int整型常量
的常量指针
,因此等号右侧是一个int整型常量
,合理。
📌 根据前面对顶层const
和底层const
的定义,最后还需补充的是
1️⃣ int *const p
是一个顶层const
。
2️⃣ const int *const pp
既是一个顶层const
也是一个底层const
。
🤔 4.顶层const和底层const的内容补充
“【顶层const】可以表示任意的对象是常量,这一点对任何数据类型都适用,如算术类型、类、指针等。【底层const】则与指针和引用等复合类型的基本类型部分有关。比较特殊的是,指针类型既可以是顶层const也可以是底层const,这一点和其他类型相比区别明显。”
const int x = 0; //对象x自身无法修改,这是一个顶层const
int r = 0;
int *const p = &r; //指向r的常量指针,自身指向不能再修改,这是一个顶层const
const int *p1 = &r; //p1是一个指向常量的指针,无法通过p修改r,这是一个底层const
const int &R = r; //R是一个指向常量的引用,无法通过R修改r,这是一个底层const
const int *const p2 = &x; //p2是一个指向常量的常量指针,顶层const+底层const
🏷️ 拷贝操作
“当执行对象之间的【拷贝操作】时,【顶层const不受什么影响】,有没有都一样,可以忽视,但【底层const的限制不能忽视】。要确保拷入和拷出的对象必须具有相同的底层const资格】,或者等号右边【表达式可以经过类型转换】成为左边对象的类型。”
也就是说:【忽略顶层const】的影响,只要满足等号右边【表达式可以经过类型转换】成为左边对象的类型,拷贝就可以进行👇
//在上面一份代码的基础上
int *p3 = p2; //错误:忽略顶层const,p2是一个const int*类型,p3是一个int *类型,无法类型转换
p1 = p2; //正确:忽略顶层const,p1和p2都是const int*类型
p1 = &r; //正确:右边为int *类型,左边为const int*类型,可以类型转换
primer和plus的区别简单说plus更小白更基础一些,根据自身情况选择。百度网盘的外链可能不让放,直接底下评论或私信就行。
✨如有问题欢迎在底下评论留言或私信!
如果这篇【文章】对你有帮助😄,希望可以给博主【点个赞👍】鼓励一下😘
❤️Thanks for your encouragement❤️