当前位置: 首页 > news >正文

常量const、引用、指针的大杂烩

文章目录

  • 1 普通引用
    • 1.1 对普通值的普通引用
    • 1.2 对常量值的普通引用
    • 1.3 对普通指针的普通引用
    • 1.4 对常量指针的普通引用
    • 1.5 对指针常量的普通引用
    • 1.6 对指向常量的指针常量的普通引用
  • 2 常量引用
    • 2.1 对普通值的常量引用
    • 2.2 对常量值的常量引用
    • 2.3 对普通指针的常量引用
    • 2.4 对常量指针的常量引用
    • 2.5 对指针常量的常量引用
    • 2.6 对指向常量的指针常量的常量引用
  • 3 总结

这标题,是不是听着就头大?常量(const)、引用、指针本来就 C++ 里面三个很头疼的概念,现在把他们合到一起,更想不明白了。没关系,看完本文后,你一定会对这三个概念有更清晰的认识。

首先我们分析分析,这三个合到一起,共能产生多少种不同的组合?一个对象可以是非指针类型(姑且称为一个“值”),也可以是指针类型。其中值可以是普通值,也可以是常量值;指针可以是普通指针、常量指针(指向常量,指针本身可变),指针常量(指针不可变,指向的值可变)、指向常量的指针常量(指针和指向的值都不可变)。所以一个对象可以细分为6种。而引用也有两种,一种是普通引用,一种是常量引用。这样算下来,应该是 6×2=126\times2=126×2=12 种组合了。其中标题“常量引用绑定到指向常量的常量指针”是最复杂的组合。下面我们就逐个讲清楚这些组合,如何定义,有哪些特点。

为不失严谨性,作出以下两点说明:

  • 有人说多于12种组合,因为指针可以指向另一个指针,引用也分左值引用和右值引用。没错,但我们这里不考虑多级指针,并只考虑左值引用。

  • 有人说少于12种组合,因为一些组合并不合法,无法定义。也没错,但我们不妨称之为“非法组合”。

1 普通引用

1.1 对普通值的普通引用

int i = 1;
int &ri = i;

这是最简单的。ri 就是对普通值 i 的一个普通引用。ri 可以看作 i 的一个别名:我们给函数传 ri 就是在传 i ,修改 ri 的值就是在修改 i 的值。

1.2 对常量值的普通引用

const int ci = 1;
int &rci = ci; // 非法

这是非法的。我们不能把一个常值绑到一个非常量引用上。理由是,如果可以绑定,则可以通过 rci 修改 ci ,而 ci 是常值,这不就矛盾了吗。因此 C++ 规定其为非法。

1.3 对普通指针的普通引用

int i = 1;
int *p = &i;
int *&rp = p;

这是第一个复合类型。怎么理解 rp 的类型名很关键。我们按照由内向外做如下解读:

rp 也是 p 的别名,用 rp 时就是在用 p 。例如通过 rp 可修改 i 的值。

*rp = 10;
std::cout << i << '\n'; // 输出10

1.4 对常量指针的普通引用

int i = 1;
const int *cp = &i;
const int *&rcp = cp;

这次类型名解读和1.3节中的类似,唯一区别是这次指针指向一个 const int 对象。正是这一区别,是我们无法通过 rcp 改变 i 的值了,正如无法通过 cp 改变 i 的值一样。

值得一提的是,因为此例中 i 不是 const int ,所以我们仍然可以改变 i 的值,此时 *cp*rcp 的值也随之变化。

i = 2;
cout << *cp << ' ' << *rcp << '\n'; // 输出2 2

所谓常量指针指向一个常量,仅是指针认为它指向常量,至于实际到底指向什么,常量还是非常量都是可以的。我们称之为指针被欺骗(见2.1节)。如果我们把一开始就把 i 定义成 const int 类型的,就使 cp 变成指向一个真正的常量的指针了。

1.5 对指针常量的普通引用

int i = 1;
int *const pc = &i;
int *&rpc = pc; // 非法

这是第二个非法组合。原因类似,因为指针常量 pc 是顶层 const,我们无法把一个普通的引用绑定到顶层 const上,否则就能通过 rpc 修改一个常量 pc 了,矛盾了。

1.6 对指向常量的指针常量的普通引用

int i = 1;
const int *const cpc = &i;
const int *&rcpc = cpc; // 非法

这是第三个非法组合,原因同上。

普通引用的六种组合到这里就讲完了,总结一下,非法的三种组合都是自己本身就是常量的,而普通引用禁止绑定到常量上,常量只能被常量引用绑定。这就来到下一节了:常量引用。

2 常量引用

2.1 对普通值的常量引用

int i = 1;
const int &cri = i;

把常量引用绑定到普通值上,就好比让常量指针指向一个非常量,都是虚假的绑定/指向,我们可以戏称之为:引用/指针被欺骗了。这里常量引用以为自己绑到了常量上,所以拒绝通过 cri 来修改 i;但是实际上 i 不是常量,所以可以通过 i 自己修改 i 的,此时 cri 的值也跟着变。

i = 3;
std::cout << cri << '\n'; // 输出3

2.2 对常量值的常量引用

const int ci = 1;
const int &crci = ci;

这才是真正的绑到一个常量上了。这儿我问大家一个问题:对“常量”值进行“常量”引用的时候,明明有两处“常量”,可为什么语句里面只看到一个 const 关键字?可能懂的人觉得这问题很stupid,但是在写一些复杂的声明的时候,真有可能犯迷糊。提示:看看1.2节,对普通值进行常量引用时,语句里有几个 const 关键字?再看看2.1节,对普通值常量引用的语句和本节的声明引用的语句有何不同?

2.3 对普通指针的常量引用

int i = 1;
int *p = &i;
int *const &crp = p;

这个声明引用的语句也有点意思,我们解读一下。

可以看到,这也是个被欺骗的引用。我们不能改 crp 的值,因为它以为自己绑的是常量,不过,它以为它以为的就是它以为的?我们还是可以改 p,此时 crp 跟着变。另一方面,虽然我们不能改 crp ,但我们可以改 *crp,因为 crp 指向一个普通的 int 变量。

*crp = 9;
cout << i << '\n'; // 输出9
crp = nullptr; // 非法
p = nullptr; // 合法,p和crp都变成空指针

2.4 对常量指针的常量引用

int i = 1;
const int *cp = &i;
const int *const &crcp = cp;

这个声明和2.3的基本相似,唯一区别在于指针指向的是一个 const int 对象。造成的影响就是不能再改 *crcp 了,但 crcp 仍是被欺骗的引用,因为它绑的是底层 const,而非顶层 const。

*crcp = 9; // 非法
crcp = nullptr; // 非法
cp = nullptr; // 合法,cp和crcp都变成空指针

2.5 对指针常量的常量引用

int i = 1;
int *const pc = &i;
int *const &crpc = pc;

这个引用的声明和2.3节非常像,大家要注意区分,还是思考那个问题,为什么对指针“常量”进行“常量”引用,只出现一个 const

我们不能修改 crpc,也不能修改 pc 。我们可以修改的是 *crpc,用它来修改 i 是可以的。

*crpc = 3;
cout << i << '\n'; // 输出3

2.6 对指向常量的指针常量的常量引用

他来了他来了,最复杂的它终于来了!

int i = 1;
const int* const cpc = &i;
const int* const &crcpc = cpc;

以上是对声明引用的解读,有了这个解读,是不是就清晰多了。从这么多常量就可以看出来了,它自己不能、也不能通过它进行任何形式的修改。

3 总结

普通引用常量引用
普通值int &ri = i;const int &cri = i;
常量值int &rci = ci; 非法const int &crci = ci;
普通指针int *&rp = p; 可以通过 rp 修改原值,可以修改 rpint *const &crp = p; 可以通过 crp 修改原值,不能修改 crp
常量指针const int *&rcp = cp; 无法通过 rcp 修改原值,可以修改 rcpconst int *const &crcp = cp; 不能通过 crcp 修改原值,不能修改 crcp
指针常量int *&rpc = pc; 非法int *const &crpc = pc; 可以通过 crpc 修改原值,不能修改 crpc
指向常量的指针常量const int *&rcpc = cpc; 非法const int* const &crcpc = cpc; 不可以通过 crcpc 修改原值,不能修改 crcpc

完结撒花~

相关文章:

常量const、引用、指针的大杂烩

文章目录1 普通引用1.1 对普通值的普通引用1.2 对常量值的普通引用1.3 对普通指针的普通引用1.4 对常量指针的普通引用1.5 对指针常量的普通引用1.6 对指向常量的指针常量的普通引用2 常量引用2.1 对普通值的常量引用2.2 对常量值的常量引用2.3 对普通指针的常量引用2.4 对常量…...

宝塔搭建实战php开源likeadmin通用管理移动端uniapp源码(四)

大家好啊&#xff0c;我是测评君&#xff0c;欢迎来到web测评。 上一期给大家分享了pc端的部署方式&#xff0c;今天来给大家分享uniapp端在本地搭建&#xff0c;与打包发布到宝塔的方法。感兴趣的朋友可以自行下载学习。 技术架构 vscode node16 vue3 uniapp vite types…...

Hive的分区表与分桶表内部表外部表

文章目录1 Hive分区表1.1 Hive分区表的概念&#xff1f;1.1.1 分区表注意事项1.2 分区表物理存储结构1.3 分区表使用场景1.4 静态分区表是什么&#xff1f;1.4.1 静态分区表案例1.4.2 分区表练习一1.4.3 分区操作1.5 动态分区表是什么&#xff1f;1.5.1 动态态分区表案例&#…...

和数集团打造《神念无界:源起山海》,诠释链游领域创新与责任

首先&#xff0c;根据网上资料显示&#xff0c;一部《传奇》&#xff0c;二十年热血依旧。 《传奇》所缔造的成绩&#xff0c;承载的是多少人的青春回忆&#xff0c;《传奇》无疑已经在游戏史上写下了浓墨重彩的一笔。 相比《传奇》及背后的研发运营公司娱美德名声大噪&#x…...

小白入门模拟IC设计,如何快速学习?

众所周知&#xff0c;模拟电路很难学。以最普遍的晶体管来说&#xff0c;我们分析它的时候必须首先分析直流偏置&#xff0c;其次在分析交流输出电压。可以说&#xff0c;确定工作点就是一项相当麻烦的工作&#xff08;实际中来说&#xff09;&#xff0c;晶体管的参数多、参数…...

51单片机——中断系统之外部中断实验,小白讲解,相互学习

中断介绍 中断是为使单片机具有对外部或内部随机发生的事件实时处理而设置的&#xff0c;中断功能的存在&#xff0c;很大程度上提高了单片机处理外部或内部事件的能力。它也是单片机最重要的功能之一&#xff0c;是我们学些单片机必须要掌握的。 为了更容易的理解中断概念&…...

如何设计一个秒杀系统

秒杀系统要如何设计&#xff1f; 前言 高并发下如何设计秒杀系统&#xff1f;这是一个高频面试题。这个问题看似简单&#xff0c;但是里面的水很深&#xff0c;它考查的是高并发场景下&#xff0c;从前端到后端多方面的知识。 秒杀一般出现在商城的促销活动中&#xff0c;指定…...

厄瓜多尔公司注册方案

简介&#xff1a; 经济概况与商机 厄瓜多尔是世界上第74大国家&#xff0c;是南美西部国家&#xff0c;与哥伦比亚&#xff0c;秘鲁和太平洋接壤。厄瓜多尔地处世界中心&#xff0c;地理位置优越&#xff0c;地理位置优越-赤道线零纬度&#xff0c;使其成为通往太平洋的理想枢…...

安全渗透环境准备(工具下载)

数据来源 01 一些VM虚拟机的安装 攻击机kali&#xff1a; kali官网 渗透测试工具Kali Linux安装与使用 kali汉化 虚拟机网络建议设置成NAT模式&#xff0c;桥接有时不稳定。 靶机OWASP_Broken_Web_Apps&#xff1a; 迅雷下载 网盘下载 安装教程 开机之后需要登录&am…...

118.(leaflet篇)leaflet空间判断-点与geojson面图层的空间关系(turf实现)

听老人家说:多看美女会长寿 地图之家总目录(订阅之前建议先查看该博客) 文章末尾处提供保证可运行完整代码包,运行如有问题,可“私信”博主。 效果如下所示: 下面献上完整代码,代码重要位置会做相应解释 <!DOCTYPE html> <html>...

目标检测与目标跟踪算法技术汇总

现如今chatgpt的爆火&#xff0c;我也使用了一段时间&#xff0c;问了许多关于人工智能技术的问题&#xff0c;基本是它能够回答了大部分的原理的&#xff0c;至于其人工智能涉及到的算法以及网络&#xff0c;考虑到也没有图&#xff0c;可能在给出这类回答上&#xff0c;是不太…...

Linux 系统启动过程

过去几十年&#xff0c;公用事业行业发生了重大变化。能源需求的转变导致企业利润率的波动&#xff0c;但不是运营成本的波动。 许多公用事业公司通过后勤部门流程自动化来削减成本&#xff0c;比如招采流程自动化。 在招采活动中&#xff0c;人工招采会产生盲点。由于公共事业…...

【每日一题Day118】LC1124表现良好的最长时间段 | 前缀和+单调栈/哈希表

表现良好的最长时间段【LC1124】 给你一份工作时间表 hours&#xff0c;上面记录着某一位员工每天的工作小时数。 我们认为当员工一天中的工作小时数大于 8 小时的时候&#xff0c;那么这一天就是「劳累的一天」。 所谓「表现良好的时间段」&#xff0c;意味在这段时间内&#…...

vue使用nprogress(进度条)

目录 1.安装 2.引入 3.配置 4.使用 5.使用场景 6.改变颜色 1.安装 npm install --save nprogress2.引入 import NProgress from nprogress import nprogress/nprogress.css3.配置 NProgress.configure({easing: ease, // 动画方式&#xff0c;和css动画属性一样&#…...

@NotNull 、@NotBlank、@NotEmpty区别和使用

引言 今天在使用validation校验的时候&#xff0c;发现了使用校验不起作用&#xff0c;一时间有点摸不到头绪&#xff0c;就看了一下同事提交的代码&#xff0c;发现了问题在用NotNull用法&#xff0c;用的有些错误&#xff0c;所以在这里讲一下NotNull、NotBlank、NotEmpty区…...

Nacos——Nacos简介以及Nacos Server安装

资料来源&#xff1a;02-Nacos配置管理-什么是配置中心_哔哩哔哩_bilibili nacos记得下载2.x版本的&#xff0c;负责以后新建配置的时候会出现“发布错误&#xff0c;请检查参数是否正确”错误&#xff01;&#xff01;&#xff01;&#xff01; 目录 一、Nacos简介 1.1 四…...

Presto 文档和笔记

1. Presto Presto 官网 Presto 文档 2. 配置 3.1 node 配置 cat etc/node.properties # Generated by Apache Ambari. Fri Feb 10 14:52:10 2023node.data-dir/mnt/bmr/presto/data node.environmentproduction node.idbmr-master-4b7cbaa3.2 jvm 配置 cat etc/jvm.confi…...

大尺度衰落与小尺度衰落

一. 大尺度衰落 无线电磁波信号在收发天线长距离&#xff08;远大于传输波长&#xff09;或长时间范围发生的功率变化&#xff0c;称为大尺度衰落&#xff0c;一般可以用路径损耗模型来描述&#xff0c;路径损耗是由发射功率在空间中的辐射扩散造成的&#xff0c;根据功率传输…...

完美解决:重新安装VMware Tools灰色。以及共享文件夹的创建(centos8)

解决&#xff1a;重新安装VMware Tools灰色问题&#xff1a;重新安装VMware Tools灰色解决方案-挂载VMware中的linux.iso1. vmtools的linux.iso挂载及安装2. 共享文件夹的创建及配置问题&#xff1a;重新安装VMware Tools灰色 发现一个小问题&#xff0c;我的vm虚拟机安装后发…...

达梦数据库作业管理

一、基本功能 作业系统大致包含作业&#xff0c;警报&#xff0c;操作员三部分。 作业可运行DMPL/SQL脚本&#xff0c;定期备份数据库&#xff0c;检查等。可定时执行&#xff0c;也可通过警报触发执行&#xff0c;可产生警报通知用户状态。一个作业由多个步骤组成&#xff0c…...

C++初阶-list的底层

目录 1.std::list实现的所有代码 2.list的简单介绍 2.1实现list的类 2.2_list_iterator的实现 2.2.1_list_iterator实现的原因和好处 2.2.2_list_iterator实现 2.3_list_node的实现 2.3.1. 避免递归的模板依赖 2.3.2. 内存布局一致性 2.3.3. 类型安全的替代方案 2.3.…...

CVPR 2025 MIMO: 支持视觉指代和像素grounding 的医学视觉语言模型

CVPR 2025 | MIMO&#xff1a;支持视觉指代和像素对齐的医学视觉语言模型 论文信息 标题&#xff1a;MIMO: A medical vision language model with visual referring multimodal input and pixel grounding multimodal output作者&#xff1a;Yanyuan Chen, Dexuan Xu, Yu Hu…...

MongoDB学习和应用(高效的非关系型数据库)

一丶 MongoDB简介 对于社交类软件的功能&#xff0c;我们需要对它的功能特点进行分析&#xff1a; 数据量会随着用户数增大而增大读多写少价值较低非好友看不到其动态信息地理位置的查询… 针对以上特点进行分析各大存储工具&#xff1a; mysql&#xff1a;关系型数据库&am…...

Debian系统简介

目录 Debian系统介绍 Debian版本介绍 Debian软件源介绍 软件包管理工具dpkg dpkg核心指令详解 安装软件包 卸载软件包 查询软件包状态 验证软件包完整性 手动处理依赖关系 dpkg vs apt Debian系统介绍 Debian 和 Ubuntu 都是基于 Debian内核 的 Linux 发行版&#xff…...

(二)TensorRT-LLM | 模型导出(v0.20.0rc3)

0. 概述 上一节 对安装和使用有个基本介绍。根据这个 issue 的描述&#xff0c;后续 TensorRT-LLM 团队可能更专注于更新和维护 pytorch backend。但 tensorrt backend 作为先前一直开发的工作&#xff0c;其中包含了大量可以学习的地方。本文主要看看它导出模型的部分&#x…...

CMake基础:构建流程详解

目录 1.CMake构建过程的基本流程 2.CMake构建的具体步骤 2.1.创建构建目录 2.2.使用 CMake 生成构建文件 2.3.编译和构建 2.4.清理构建文件 2.5.重新配置和构建 3.跨平台构建示例 4.工具链与交叉编译 5.CMake构建后的项目结构解析 5.1.CMake构建后的目录结构 5.2.构…...

HTML 列表、表格、表单

1 列表标签 作用&#xff1a;布局内容排列整齐的区域 列表分类&#xff1a;无序列表、有序列表、定义列表。 例如&#xff1a; 1.1 无序列表 标签&#xff1a;ul 嵌套 li&#xff0c;ul是无序列表&#xff0c;li是列表条目。 注意事项&#xff1a; ul 标签里面只能包裹 li…...

【机器视觉】单目测距——运动结构恢复

ps&#xff1a;图是随便找的&#xff0c;为了凑个封面 前言 在前面对光流法进行进一步改进&#xff0c;希望将2D光流推广至3D场景流时&#xff0c;发现2D转3D过程中存在尺度歧义问题&#xff0c;需要补全摄像头拍摄图像中缺失的深度信息&#xff0c;否则解空间不收敛&#xf…...

在 Nginx Stream 层“改写”MQTT ngx_stream_mqtt_filter_module

1、为什么要修改 CONNECT 报文&#xff1f; 多租户隔离&#xff1a;自动为接入设备追加租户前缀&#xff0c;后端按 ClientID 拆分队列。零代码鉴权&#xff1a;将入站用户名替换为 OAuth Access-Token&#xff0c;后端 Broker 统一校验。灰度发布&#xff1a;根据 IP/地理位写…...

屋顶变身“发电站” ,中天合创屋面分布式光伏发电项目顺利并网!

5月28日&#xff0c;中天合创屋面分布式光伏发电项目顺利并网发电&#xff0c;该项目位于内蒙古自治区鄂尔多斯市乌审旗&#xff0c;项目利用中天合创聚乙烯、聚丙烯仓库屋面作为场地建设光伏电站&#xff0c;总装机容量为9.96MWp。 项目投运后&#xff0c;每年可节约标煤3670…...