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

理解 C++ 中的顶层 const 与底层 const(二十四)

1. 示例解析

下面的代码展示了不同 const 限定符的组合及其含义:

int i = 0;
int *const p1 = &i;       // p1 是一个常量指针:p1 本身不可改变(顶层 const),但 *p1 所指的 int 可修改
const int ci = 42;        // ci 是一个常量整型,属于顶层 const:ci 的值不可改变
const int *p2 = &ci;      // p2 是一个指向常量的指针:可以改变 p2 的值(即指向不同对象),但不能通过 p2 修改其所指对象(底层 const)

再看一个组合示例:

const int *const p3 = p2;
  • 靠右的 const 限定的是 p3 本身,即 p3 是一个常量指针(顶层 const),它的值(地址)一旦初始化后不能再改变。
  • 靠左的 const 限定的是 p3 所指向的对象,即 p3 指向的对象被视作常量(底层 const)。

另外,对于引用来说,声明时出现的 const 都视作底层 const,例如:

const int &r = ci;  // r 是对 ci 的常量引用

2. 拷贝操作中的顶层 const 与底层 const

在执行拷贝操作时,顶层 const 与底层 const 的区别尤为重要:

2.1 顶层 const 不影响拷贝

顶层 const 限定的是对象本身,在拷贝时仅拷贝其值,不受 const 限定的影响。例如:

int i = 0;
const int ci = 42;  // ci 是顶层 const
i = ci;             // 正确:这里仅是拷贝 ci 的值,ci 本身未改变

同样,对于指针来说:

const int *p2 = &ci;
const int *const p3 = p2;  // p3 同时具备顶层 const(指针不可改)和底层 const(所指对象不可改)
p2 = p3;                   // 正确:p3 的顶层 const 不影响拷贝,只需保证 p2 和 p3 的底层类型匹配

2.2 底层 const 的限制

底层 const 限定的是复合类型内部所指向对象的类型,在拷贝或赋值时,必须确保拷贝双方的底层 const 资格匹配。常见规则是“非常量可以转换成常量,但反之则不行”。例如:

// 错误示例:试图将带有底层 const 的指针赋值给普通指针
const int *p_const = &ci;
int *p_nonconst = p_const;  // 错误:p_const 指向的对象被视为常量,不能赋给允许修改的 int*

而下面这种转换则是允许的:

// 正确:普通指针可以转换成指向常量的指针
int j = 10;
int *p_j = &j;
const int *p_const2 = p_j;   // 合法:p_const2 将视 j 为 const,但 j 仍可通过其他非 const 的引用修改

此外,下面的赋值也是错误的,因为将一个指向常量的引用或指针绑定到非 const 对象上,会破坏底层 const 的约束:

int i = 42;
const int &r1 = i;  // 合法:允许将常量引用绑定到普通对象上
int &r2 = r1;       // 错误:试图通过非常量引用修改 r1 所绑定的对象(r1 中的底层 const 不允许通过此途径修改)

3. 小结与建议

  • 顶层 const 用于描述对象本身的不可修改性,不会影响对象值的拷贝或赋值。

    • 例如 const int ci = 42; 中,ci 的值拷贝给其他变量时不会因 const 而受限。
  • 底层 const 限定复合类型中被指向(或绑定)的对象的类型。拷贝操作时,必须确保底层类型的一致性。

    • 例如,const int *p2 表示通过 p2 不能修改所指向的整数,而将其赋值给允许修改目标的普通指针是错误的。
  • 对于指针来说,既可能具有顶层 const 也可能具有底层 const。要理解其含义,建议从右向左阅读声明:

    • int *const p1:p1 是一个常量指针(顶层 const),但其指向的对象可修改;
    • const int *p2:p2 是一个指向常量的指针(底层 const),但 p2 本身可修改指向;
    • const int *const p3:p3 同时具备顶层和底层 const,既不能改变指针的地址,也不能通过它修改目标数据。
  • 拷贝和赋值操作中,顶层 const 部分不影响数据拷贝,而底层 const 则必须保持一致,否则将导致转换错误。

正确区分顶层 const 与底层 const,对于编写安全、清晰的代码至关重要。在实际开发中,建议在书写指针、引用声明时注意 const 的位置,并在必要时添加注释,帮助自己和团队成员更快地理解代码中 const 的语义。

参考资料

  • cppreference.com 中关于 const 限定符、链接性与转换的详细说明
  • 各大 C++ 编码风格指南(如 Google C++ Style Guide)中对 const 的应用建议

通过深入理解 const 的顶层与底层含义,你可以在代码设计上更明确地表达意图,避免不必要的错误,并使程序更易于维护和扩展。

相关文章:

理解 C++ 中的顶层 const 与底层 const(二十四)

1. 示例解析 下面的代码展示了不同 const 限定符的组合及其含义: int i 0; int *const p1 &i; // p1 是一个常量指针:p1 本身不可改变(顶层 const),但 *p1 所指的 int 可修改 const int ci 42; …...

Linux之数据链路层

Linux之数据链路层 一.以太网1.1以太网帧格式1.2MAC地址1.3MTU 二.ARP协议2.1ARP协议工作流程2.2ARP协议格式 三.NAT技术四.代理服务4.1正向代理4.2反向代理 五.四大层的学习总结 一.以太网 在我们学习完了网络层后我们接下来就要进入数据链路层的学习了,在学习完网…...

如何在 vue 渲染百万行数据,vxe-table 渲染百万行数据性能对比,超大量百万级表格渲染

vxe-table 渲染百万行数据性能对比,超大量百万级表格渲染;如何在 vue 渲染百万行数据;当在开发项目时,遇到需要流畅支持百万级数据的表格时, vxe-table 就可以非常合适了,不仅支持强大的功能,虚…...

std::reference_wrapper 和 std::function的详细介绍

关于 std::reference_wrapper 和 std::function 的详细介绍及具体测试用例: 1. std::reference_wrapper(引用包装器) 核心功能 包装引用:将引用转换为可拷贝、可赋值的对象支持隐式转换:可自动转换为原始引用类型容器…...

如何封装一个上传文件组件

#今天用el-upload感到很多不方便,遂决定自己封装一个。注:本文不提供表面的按钮样式和文件上传成功后的样式,需要自己创建。本文仅介绍逻辑函数# 1,准备几个表面用来指引上传的元素 2,创造统一的隐藏文件上传输入框&…...

MySQL-5.7.37安装配置(Windows)

1.下载MySQL-5.7.37软件包并解压 2.配置本地环境变量 打开任务栏 搜索高级系统设置 新建MySQL的环境变量 然后在path中添加%MYSQL_HOME%\bin 3.在MySQL-5.7.37解压的文件夹下新建my.ini文件并输入以下内容 [mysqld]#端口号port 3306#mysql-5.7.27-winx64的路径basedirC:\mysq…...

CentOS与Ubuntu命令对比指南:从软件包管理到系统配置

CentOS与Ubuntu命令对比指南 作为两大主流Linux发行版,**CentOS(基于RHEL)和Ubuntu(基于Debian)**在日常运维中常因命令差异引发混淆。本文通过关键场景对比,助您快速掌握两者的核心操作区别。 一、软件包管理:yum/dnf vs apt 操作CentOSUbuntu更新软件源yum check-upd…...

鸿蒙北向应用开发:deveco 5.0 kit化文件相关2

鸿蒙北向应用开发:deveco 5.0 kit化文件相关 在kit化时,有时候会出现这样一种场景即你想把已有的d.ts导出换个名字,这样从名字上更贴合你的kit聚合 什么意思呢?比如现在有 ohos.hilog.d.ts 导出了hilog,现在你想kit化hilog,使得hilog导出名字为usrhilog,这样用户在使用你的k…...

《HelloGitHub》第 108 期

兴趣是最好的老师,HelloGitHub 让你对开源感兴趣! 简介 HelloGitHub 分享 GitHub 上有趣、入门级的开源项目。 github.com/521xueweihan/HelloGitHub 这里有实战项目、入门教程、黑科技、开源书籍、大厂开源项目等,涵盖多种编程语言 Python、…...

C++可变参数

可变参数C风格的可变参数C风格可变参数的使用 C11可变参数模板递归展开参数包参数列表展开折叠表达式 STL中的emplace插入接口 可变参数 C风格的可变参数 可变参数是一种语言特性,可以在函数声明中使用省略号...来表示函数接受可变数量的参数。 例如典型的printf…...

光传输设备现状

随着运营商准备好其基础设施以应对新一代高带宽应用程序和 AI 部署,光传输网络 (OTN) 市场再次有望实现稳健增长。 隧道的尽头有光亮,OTN 市场在 2024 年最后一个季度表现强劲,设备供过于求的时代已经结束。 供应商表示设备订单量有所增加&…...

Python 笔记 (二)

Python Note 2 1. Python 慢的原因2. 三个元素3. 标准数据类型4. 字符串5. 比较大小: 富比较方法 rich comparison6. 数据容器 (支持*混装* )一、允许重复类 (list、tuple、str)二、不允许重复类 (set、dict)1、集合(set)2、字典(dict)3、特殊: 双端队列 deque 三、数据容器的共…...

nt!IopCompleteReques函数分析之IopUpdateOtherTransferCount和IopDequeueThreadIrp

VOID IopCompleteRequest( IN PKAPC Apc, IN PKNORMAL_ROUTINE *NormalRoutine, IN PVOID *NormalContext, IN PVOID *SystemArgument1, IN PVOID *SystemArgument2 ) 第一部分: if (irp->UserEvent) { (VOID) KeSetEvent( …...

d2025329

目录 一、修复表中名字 二、患某种疾病的患者 三、最长连续子序列 四、二叉树的层序遍历 一、修复表中名字 1667. 修复表中的名字 - 力扣(LeetCode) concat(A,B),将字符串A和B拼接left(str,len),从字符串左边开始截取len个字…...

北斗导航 | 中国北斗卫星导航系统的发展历程——“三步走”战略:背景,信号频点,调制方式,短报文,等

中国北斗卫星导航系统的发展历程按照“三步走”战略逐步推进,从区域服务到全球覆盖,形成了北斗一号、北斗二号、北斗三号三代系统的迭代升级,展现了中国航天科技的自主创新与突破。以下是各阶段的核心内容与发展特点综述:一、北斗一号:中国卫星导航的奠基(1994-2003年) …...

cordova android12+升级一些配置注意事项

1.以android13为例 Cordova Android 13.0.0 cordova platform remove android cordova platform add android13.0.0Cordova Android 13.0.0 这里建议将android-studio升级到最新 build时若是需要到gradled安装失败 建议多试几次 或者直接用网页下载 找到 Android Studio 的 G…...

批量处理word里面表格的空白行

1,随便打开一个word文档。 2,按下Alt F11 VBA编辑器,在左侧的「工程资源管理器」窗口中找到Normal 项目,右键选择插入->模块。 弹出一下弹窗 3,输入一下代码 代码: Sub RemoveEmptyTableRows()Dim tbl As TableDim row As R…...

K8S学习之基础五十七:部署代码扫描工具sonarqube

部署代码扫描工具sonarqube 拉取postgres、sonarqube镜像,在harbor上创建postgres、sonarqube项目,将镜像上传至harbordocker pull postgres docker pull sonarqube docker tat postgres:latest 172.16.80.140/postgres/postgres:latest docker tat sona…...

Nginx 解决具有不安全、不正确或缺少 SameSite 属性的 Cookie方案

针对Nginx中Cookie的SameSite属性配置问题,以下是综合解决方案及注意事项: 一、基础配置方法 全局设置Cookie属性‌(适用于Nginx直接生成Cookie) 在nginx.conf的location块中通过add_header指令添加: add_header Se…...

音频知识 参数分析

通道布局 参考 通过pcm音频数据计算分贝 理解FFT和信号加窗原理及意义 dts音效大师教程...

使用 rsync 进行服务器文件同步与优化

使用 Rsync 工具在两台 Linux 服务器之间同步文件 Rsync 是一种高效的文件同步工具,它可以在本地或远程服务器之间同步文件和目录。Rsync 通过仅传输文件的变化部分来减少数据传输量,因此特别适合用于定期备份或同步大量数据。本文将详细介绍如何将 A 服…...

MySQL 的 SQL 语句执行顺序

MySQL 的 SQL 语句执行顺序并不完全按照代码的书写顺序执行,而是遵循一套固定的逻辑流程 1. FROM 和 JOIN 作用:确定查询的数据来源,包括表和它们的连接方式(如 INNER JOIN, LEFT JOIN 等)。 细节: 先执行…...

小型水库大坝安全及水雨情监测技术方案

一、小型水库监测系统构成 小型水库雨水情测报和大坝安全监测系统由水库监测站点、通信网络和监测平台等组成,系统总体架构如图所示。 水库监测站点设施包括:雨量计、水位计、视频监视设备、渗压计、量水堰计、变形监测仪器、数据采集仪、遥测终端、水准…...

scala简介和基础语法

Scala简介 Scala 是一门多范式(multi-paradigm)的编程语言,设计初衷是要集成面向对象编程和函数式编程的各种特性。 Scala 运行在 Java 虚拟机上,并兼容现有的 Java 程序。Scala 源代码被编译成 Java 字节码,所以它可…...

‘无法定位程序输入点kernel32.dll’详细的修复方法,一键快速修复kernel32.dll

在 Windows 系统运行过程中,若程序提示“无法定位程序输入点 kernel32.dll”,往往意味着程序调用了 kernel32.dll 中不存在或已变更的函数接口。作为系统的核心动态链接库,kernel32.dll 承担着内存管理、进程控制、文件操作等底层功能&#x…...

电源系统的热设计与热管理--以反激式充电器为例

前言 反激电源常用于各种电子设备中,比如充电器、适配器等,它们通过变压器进行能量转换。高温环境可能对电子元件造成影响,特别是像MOSFET、二极管、变压器这样的关键部件,导致效率变低,甚至可能导致功能失效。还有安…...

笔记本电脑更换主板后出现2203:System configuration is invalid,以及2201、2202系统错误的解决

笔记本电脑更换主板后启动出现2203:System configuration is invalid,以及2201、2202系统错误的解决 自用的一台ThinkpadT490笔记本电脑 ,由于主板故障,不得不更换主板,通过某宝购置主板后进行了更换。 具体拆卸笔记本可搜索网络视频教程。 注意: 在更换主板时,注意先拍…...

项目-苍穹外卖(十七) Apache POI+导出数据

一、介绍 二、入门案例 package com.sky.test;import org.apache.poi.xssf.usermodel.XSSFRow; import org.apache.poi.xssf.usermodel.XSSFSheet; import org.apache.poi.xssf.usermodel.XSSFWorkbook;import java.io.File; import java.io.FileNotFoundException; import jav…...

蓝桥杯单片机刷题——E2PROM记录开机次数

设计要求 使用E2PROM完成数据记录功能,单片机复位次数记录到E2PROM的地址0中。每复位一次数值加1,按下按键S4,串口发送复位次数。串口发送格式如下: Number:1 备注: 单片机IRC振荡器频率设置为12MHz。 …...

聚合根的特性

聚合根的特性 聚合根是实体,拥有实体的业务属性和行为,同时也是聚合的管理者,负责协调聚合内的实体和值对象,按照固定的业务规则,完成业务逻辑。 聚合根是聚合对外唯一的接口人,聚合之间以聚合根ID关联的方…...