C++中顶层const与底层const

在C++中,const关键字用于定义常量,但它在指针和引用上下文中会产生两种不同的常量性:顶层const(top-level const)底层const(low-level const)。理解它们的区别是避免编译错误和提高代码质量的关键。


1. 核心概念解析
类型含义典型场景
顶层const对象本身不可被修改指针本身是常量
底层const指针/引用指向的对象不可被修改指向常量数据的指针/引用

2. 指针场景详解(含示例代码)
int x = 10, y = 20;// 情况1: 顶层const(指针本身为常量)
int* const p1 = &x;  // p1的地址不可变
*p1 = 30;            // ✅ 合法:修改x的值
// p1 = &y;          // ❌ 错误:p1的地址不可变// 情况2: 底层const(指向的数据为常量)
const int* p2 = &x;  // p2指向的数据不可变
// *p2 = 40;         // ❌ 错误:试图修改常量数据
p2 = &y;             // ✅ 合法:更改指针地址// 情况3: 双重const
const int* const p3 = &x; // 地址和数据均不可变
// *p3 = 50;              // ❌ 错误
// p3 = &y;               // ❌ 错误

3. 引用场景详解

引用只有底层const(本身绑定关系不可变,因此不需要顶层const):

int a = 100;
const int& r = a;   // r是底层const
// r = 200;        // ❌ 错误:无法通过r修改a
a = 200;            // ✅ 合法:直接修改a(r的值同步变为200)

4. 关键规则与实战应用
  1. 拷贝操作中的限制

    • ✅ 底层const → 底层const:安全(权限保留)
      const int* src = &x;
      const int* dest = src; // 合法:底层const匹配
      
    • ❌ 非底层const → 底层const:需要显式类型转换
      int* src = &x;
      const int* dest = src;  // ✅ 合法:增加底层const
      // int* dest = src_const; // ❌ 错误:放弃底层const需强制转换
      
  2. 函数重载中的影响
    顶层const不影响重载,底层const会产生不同签名:

    void func(int* p);        // #1
    void func(const int* p);  // #2 不同函数(底层const)void func(int i);         // #3
    void func(const int i);   // ❌ 与#3冲突(顶层const无效)
    
  3. const成员函数
    隐含底层const:this指针变为const T*

    class MyClass {
    public:void modify() { /* 可修改成员 */ }void inspect() const { /* 只读成员 */ } // 底层const:this -> const MyClass*
    };
    

5. 判断技巧表格
声明形式顶层const底层const可修改部分
int* const ptr*ptr的值
const int* ptrptr指向的地址
const int& ref-原变量(非通过ref)
const int* const p

6. 总结与最佳实践
  • 顶层const:保护容器(指针/对象本身),编译器直接校验。
  • 底层const:保护内容(指向的数据),影响类型系统和函数交互。
  • 设计原则
    1. 优先使用底层const保护函数参数(避免意外修改)
    2. const成员函数应严格遵循只读约定
    3. 使用const_cast谨慎突破底层const(通常表示设计问题)

透彻理解顶层/底层const的区别,是写出健壮、安全的C++代码的基石。常量性的正确应用能显著提升代码的可维护性和安全性。

推荐:C++学习一站式分享

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/88843.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/88843.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

“SRP模型+”多技术融合在生态环境脆弱性评价模型构建、时空格局演变分析与RSEI指数生态质量评价

集成云端、桌面端等环境,结合遥感云计算、GIS空间分析,R语言统计分析的优势,以分析生态环境脆弱性的时空演变为主线。通过本课程的学习,您将掌握:第一,收集各类指标数据,构建的“生态压力度-生态…

算法学习笔记:17.蒙特卡洛算法 ——从原理到实战,涵盖 LeetCode 与考研 408 例题

在计算机科学和数学领域,蒙特卡洛算法(Monte Carlo Algorithm)以其独特的随机抽样思想,成为解决复杂问题的有力工具。从圆周率的计算到金融风险评估,从物理模拟到人工智能,蒙特卡洛算法都发挥着不可替代的作…

Tortoise 设置

如何关闭 Windows 下 TortoiseGit 任务栏里窗口标题的分支显示 一、引言 TortoiseGit 是一个专为团队协作设计的 Git 图形化客户端,旨在解决版本控制中常见的问题,如冲突、回滚、历史查看等。本文档是 TortoiseGit 的使用手册前言部分,旨在向…

[论文阅读] 人工智能 + 软件工程 | AI助力软件可解释性:从用户评论到自动生成需求与解释

AI助力软件可解释性:从用户评论到自动生成需求与解释 Automatic Generation of Explainability Requirements and Software Explanations From User ReviewsarXiv:2507.07344 Automatic Generation of Explainability Requirements and Software Explanations From …

C语言---自定义类型(上)(结构体类型)

结构体结构体的定义与声明结构体其实和数组一样,都是一些值的集合,只不过数组是一系类相同类型的值,而结构体里边的成员可以是不同的数据类型。关于它的声明,所用到的关键字是struct。声明的语法如下:struct 结构体名{…

Java观察者模式实现方式与测试方法

一、实现方式 自定义实现 通过手动定义Subject和Observer接口,实现一对多依赖关系: // 观察者接口 public interface Observer {void update(float temp, float humidity, float pressure); } // 主题接口 public interface Subject {void registerObser…

leetGPU解题笔记(1)

1.题面 题目要求 向量加法 实现一个程序,在GPU上对两个包含32位浮点数的向量执行逐元素加法。该程序应接受两个长度相等的输入向量,并生成一个包含它们和的输出向量。 实现要求 禁止使用外部库 solve函数签名必须保持不变 最终结果必须存储在向量C中 示例…

5. JVM 的方法区

1. JVM介绍和运行流程-CSDN博客 2. 什么是程序计数器-CSDN博客 3. java 堆和 JVM 内存结构-CSDN博客 4. 虚拟机栈-CSDN博客 5. JVM 的方法区-CSDN博客 6. JVM直接内存-CSDN博客 7. JVM类加载器与双亲委派模型-CSDN博客 8. JVM类装载的执行过程-CSDN博客 9. JVM垃圾回收…

网络安全的基本练习

一.docker搭建 1.安装dockerapt-get install docker.io docker-compose2.编写配置文件(注意路径正确)vim /etc/systemd/system/docker.service.d/http-proxy.conf[Service] Environment"HTTP_PROXYhttp://科学上网访问的ip:端口" Environment&…

380. O(1) 时间插入、删除和获取随机元素

实现RandomizedSet 类: RandomizedSet() 初始化 RandomizedSet 对象 bool insert(int val) 当元素 val 不存在时,向集合中插入该项,并返回 true ;否则,返回 false 。 bool remove(int val) 当元素 val 存在时&#xff…

【LeetCode Hot100 | 每日刷题】字母异位词分组

题目链接:49. 字母异位词分组 - 力扣(LeetCode) 题目: 给你一个字符串数组,请你将 字母异位词 组合在一起。可以按任意顺序返回结果列表。 示例 1: 输入: strs ["eat", "tea", "tan"…

docker 安装windows

目录 下载地址: 使用教程: docker compose 查看版本 测试启动 hello-world 报错1 The system cannot find the file specified: 检查 Docker Desktop 是否运行中 报错2HF_ENDPOINT 1. 临时解决方案(当前终端会话有效&…

docker compose 和build

目录 docker compose 和build 的区别是什么? 核心差别: 1. docker build --platform linux/amd64 -f Dockerfile -t infiniflow/ragflow:nightly_lbg . 2. docker compose -f docker-compose-gpu.yml up -d 二者如何配合? 总结 docker …

裂变时刻:全球关税重构下的券商交易系统跃迁路线图(2025-2027)

——基于RWA清算、量子加密与实时非线性风控的下一代跨境基础设施核心事件锚定:特朗普于7月7日对14国启动分级关税制裁(日韩25%、东南亚30%-40%、金砖关联国10%附加税),引发日元兑美元暴跌至144.47、铜价单日跳涨3.2%、散户单日交…

python爬虫初入门——基本库和写入方法

1.准备环境 python环境:3.10 2.常用库 1.请求库:实现 HTTP 请求操作 requests:基于 urllib 编写的,阻塞式 HTTP 请求库,发出一个请求,一直等待服务器响应后,程序才能进行下一步处理。seleni…

Sonar扫描C#代码配置

需要的工具 MSBuild、sonar-scanner-4.6.1.2450-windows、jdk1.8.0_181 下载地址:https://download.csdn.net/download/code12313/91315686 配置sonar的地址 一、环境变量配置 1.新建变量,nameSONAR_RUNNER_MSBUILD_HOME。valueD:\work\dev\dev_serve…

python 在运行时没有加载修改后的版本

陈旧的Python字节码 (.pyc 文件):最常见的原因!Python 会把你修改的 .py 文件编译成 .pyc 字节码来加速后续运行。有时,即使你修改了 .py 文件,系统可能仍然固执地加载旧的、未被删除的 .pyc 文件。1. 用“硬编码探针”强制验证# …

【会员专享数据】2013-2024年我国省市县三级逐年SO₂数值数据(Shp/Excel格式)

之前我们分享过2013-2024年全国范围逐年SO₂栅格数据(可查看之前的文章获悉详情)!该数据来源于韦晶博士、李占清教授团队发布在国家青藏高原科学数据中心网站上的中国高分辨率高质量近地表空气污染物数据集。很多小伙伴拿到数据后反馈栅格数据…

出现SSL连接错误的原因和解决方案

介绍 SSL连接错误是一种常见但关键的问题,这可能会阻止客户端和服务器之间的安全连接。这些错误发生在TLS握手过程失败时,这意味着客户端和服务器无法建立安全的HTTPS连接。这种失败可以在SSL/TLS协商过程中的任何阶段发生,从初始协议协议到…

vue3 el-date-picker 保存后 日期减一问题

在使用 el-date-picker(Element UI 的日期选择器组件)时,如果你发现日期在保存到后台后自动减一,这通常是由于时区差异或者是时间格式解析问题导致的。这里有一些可能的解决方案:1. 检查前端发送的日期格式确保你在前端…