C++ 模板参数推导问题小记(非推导上下文)
宰荡艘鞍嗯。const顾名思义就是不变。给任何数据类型加上 const就指明了这个变量不会再变化。任何试图修改变量的操作都会报错无法通过编译。比如const int a 10;a 11; //Error!当然常量也必须在定义时初始化。常量自己不能变但这不代表不能使用。它可以被用于初始化其它对象int b a * 2;// b 20很简单的东西不是吗接下来让我们结合一下上一篇的引用和指针。常量引用我们可以使用 const 限定修饰一个引用。由于引用本身就不可以更改它绑定的对象所以这里 const 只是阻止了对绑定对象的修改而已const int a 10;int b 10;const int c a;const int d b;int e a; //Errora 11;// Errorb 11;// OK!c 11;// Errord 11;// Error看看上面的代码对 a,c,d 的修改都会产生编译错误。我们一个个分析a 是常量但是 e 是个普通引用非常量不能绑定到常量对 a 的修改是不可行的因为它是个常量对 b 的修改是可行的因为它是整型变量对 c、d 的修改不可行因为它们是常量引用不可修改也就是说……const 限定符应用在引用上时只是让 C 认为引用指向的对象不可以被修改而实际指向的对象到底是否为常量是否可以修改是没有影响的。如果已经在对象上施加 const那么指向它的引用也必须添加来保持类型一致。可以这么理解如果引用不加 const那么 C 就认为引用指向的对象可以修改这显然和对象的不可修改性不符编译器不允许这样的事情发生。试试这样想吧你可以在可以随意使用的瓶子上贴上勿动的标签但是不能给不能动的瓶子贴上可动的标签还记得我们曾经把引用比作瓶子上贴的标签那么这里的 const 限定符就好像在标签上加上一句不能动特殊用法在继续前进之前我们来看点奇怪的常量引用。int i 10;double s 3.14;const int a 1;const int b i * 2;const int c s * 2;wow这里的3、4、5行居然把表达式赋给引用会报错的。既然我都说了是奇怪的引用当然不会编译错误啦。这其实是常量引用的特殊用法如果一个引用添加了 const 限定那么编译器允许使用任意表达式包括字面值、算式、对象并且能够自动转换。你一定已经在学习指针前了解过自动转换了。如果两个变量的类型不匹配那么编译器会尝试自动转换。也就是说上方代码与下方等效int i 10;double s 3.14;int tmp1 1;const int a tmp1;int tmp2 i * 2;const int b tmp2;int tmp3 s * 2; //自动类型转换const int c tmp3;// b 20, c 6但也别搞混了这个只在引用带有 const 时生效普通引用由于是可变的所以只能绑定一个数据类型匹配的变量。恭喜你你已经掌握了引用中的 const我们一鼓作气继续看看指针中的 const。const 与指针添加 const 限定const int a 10;int b 10;const int *s a;const int *t b;int *s1 a; //Errorint *t1 b;为什么 s1 的定义会报错但是其它就不报错呢我们在常量引用中提到const 只是告诉编译器认为指向的对象不可变。举一反三const 应用于指针则表示认为指针所指的对象那个地址对应的对象不可变。这就解释了 3,4 行的定义。而第五行的报错也和上文所述相似你所指的对象不可变又怎么能够让指针认为所指的对象可变呢这是不符合常理的。认为指向对象不可变也就是解引用后获得的对象不能变化*s 11; //Error*t 11; //Error但是和引用不一样指针是对象自己是可变的。上面的 const 限定只是让指针认为自己指向的对象不可变但指针本身指向哪个对象是可变的。s b; //OKt a; //OK上面的代码完全可以正常运行。常量指针那怎么让指针自己不可变呢嗯这里事情逐渐变得复杂了起来。const int a 10;int b 10;int *const s a; //Errorint *const t b;const int *const s1 a;const int *const t1 b;Wait Wait Wait 这有点太复杂了我们还是一行行看。注意到了吗我们使用了 *const它表示定义一个常量指针。顾名思义指针本身是常量不能变不能改变保存的位置即不能修改它指向的对象是哪一个。现在来看代码第三行它定义了一个本身是常量的指针而认为指向的对象是可变的但是却绑定到了不可变常量 a因此报错上文已经强调过不能认为不可变的东西可变第四行它定义了一个本身是常量的指针绑定到了变量 b没问题。第五行它定义了一个本身是常量的指针且认为指向对象不可变绑定到了不可变常量没问题。第六行它定义了一个本身是常量的指针且认为指向对象不可变绑定到了变量没问题为了更加清晰说明什么叫本身不可变什么叫认为指向对象不可变再给出以下代码const int c 11;t c; //Errors1 c; //Errort1 c; //Error*t 12;*s1 12; //Error*t1 12; //Error仔细想想为什么那些行会报错吧。本身不可变的指针不可以重新指向其它位置。因此 2,3,4 行报错之前提到过如果指针认为自己指向的对象不可变那么它解引用后不可变所以 6,7 行报错好好思考一下分清楚什么是本身不可变什么是认为指向的对象不可变解引用后不可变。Tips还是再回忆下 const 修饰的真正含义吧。如果认为指向对象不可变那么这和指向对象实际是否可变没有任何关系。如果你理解了真得好好夸夸自己连这么复杂的东西都搞懂了顶层与底层我们把本身不可变的 const称作顶层 const认为指向对象不可变的 const称作底层 const。从之前的讲解中我们不难得到推论引用本身不可变所以只有认为不可变的底层 const 存在。对于指针如果放在距离变量名远的地方那么是底层距离变量名近的地方是顶层底层 const 只和指针、引用有关而顶层 const 可以修饰大部分对象很好。接下来我们就要涉及一些更加深入的话题了。我们曾经在特殊用法那里提过一嘴自动转换。众所周知在执行赋值操作时可能会进行自动转换。而变量可以转换为常量常量也可以转换为变量int a 10;const int b a; //b 被顶层 const 修饰它本身不可变int c b;但对于指针和引用来说事情就更加复杂了。当你赋值涉及指针、引用时源和目标的顶层 const 可以不同但顶层决定本身是否可变必须满足自动转换不可变拷贝到可变。注意上面代码第二行和下面代码最后一行。const int d 20;const int *const p1 b;const int *p2 d;p1 p2;//Errorp2 p1;//现在p1,p2 都指向 b。对于底层 const这决定了源、目标认为其所指向的对象是否可变。在此过程中源和目标的底层 const 可以不同但是底层指向对象是否可变必须满足自动转换可变拷贝到不可变。int e 1;int *p3 d; //Errorint *p4 e;p2 p4; //为变量的指针增加不可变修饰但注意一下上面只是赋值操作如果是新创建指针那么顶层 const 无所谓正如之前所述const int *const m p1;const int *m1 p1;我知道你确实有点晕了。总结一下修改指针操作时看等号左侧是否有顶层 const 很重要有顶层 const 就不能修改而任何操作时都有必要去检查下等号右侧的底层 const如果有那么左边也必须有否则左侧随意。试试这样想吧const 就是一种修饰。指针是瓶子的标签你可以让瓶子对象本身不可变顶层 const 修饰但这样你必须在标签指针上写上“别动瓶子”底层 const 修饰。如果你看到了“别动”的标签底层 const 修饰的指针想根据这个标签给瓶子再贴一个标签或者把别的瓶子上的标签移过来创建新指针/修改旧指针那么另一个标签上也得写“别动”底层 const 修饰。如果你的标签上没有“别动”没有底层 const说明瓶子本身一定是可以动的没有顶层 const所以新创建的标签写不写“别动”都无所谓有没有底层 const 并没有关系。而如果一个标签是强力胶撕不下来指针有顶层 const 修饰那么它就不能移动。但是你还是可以根据这个标签移动其它可以移动的标签将其它无顶层 const 修饰的指针赋值为它或者创建一个新的标签是否为强力胶都可以创建新的指针时顶层 const 修饰并不重要。用比喻来说顶层 const 决定了标签有没有强力胶底层 const 决定我们是否认为瓶子能动。如果有强力胶一个标签本身就不能移动了但不影响其它标签。如果我们根据一个标签不认为瓶子能动那么也就没办法再贴上能动的标签了。注意了我这里一直强调根据某个标签是因为这是在指针的语境下来说的我们必须根据指针来进行寻找对象、赋值等操作而不是直接操作对象。好好想想上文所述“根据某个标签”指的就是赋值等号右侧的内容。你也可以配上下面的表格举例一起理解注意代码是无法运行的这里只是为了看清楚而写出了每个类型所以没有用赋值的等号当操作为创建指针并赋值时int *p - const int a Error 试图认为不可变的常量可变const int *p - const int a OKconst int *p - int a OKint *p1 - int *const p OKint *const p1 - int *const p OKconst int *p1 - int *const p OKconst int *p1 - int *p OKconst int *const p1 - int *p OKconst int *const p1 - int *const p OKconst int *const p1 - const int *const p OKconst int *p1 - const int *const p OKint *const p1 - const int *p Error 试图根据指向不可变对象的指针认为指向可变对象int *const p1 - const int *const p Error 试图根据指向不可变对象的指针认为指向可变对象当操作为修改左侧已经创建的指针时int *p - const int a Error 试图认为不可变的常量可变const int *p - const int a OKconst int *p - int a OKint *p1 - int *const p OKint *const p1 - int *const p Error 试图修改不可变的指针const int *p1 - int *const p OKconst int *p1 - int *p OKconst int *const p1 - int *p Error 试图修改不可变的指针const int *const p1 - int *const p Error 试图修改不可变的指针const int *const p1 - const int *const p Error 试图修改不可变的指针const int *p1 - const int *const p OKint *const p1 - const int *p Error 试图根据指向不可变对象的指针认为指向可变对象 / 试图修改不可变的指针int *const p1 - const int *const p Error 试图根据指向不可变对象的指针认为指向可变对象 / 试图修改不可变的指针OKOKOK我知道这很难但是再读一遍理解一下指针的 const 修饰吧。哦对了赋值记得保证除了 const 外的数据类型一致。别忘了这个基础。如果你连这个都掌握了你已经对 const 有了相当程度的认识。恭喜下一篇我们将离开指针的苦海继续讲解 C。当然也是奶奶级的拆解哦。本文作者SamHou0。原文链接https://www.cnblogs.com/samhou/p/19150553/cpp-pointer-const-guide本文的所有发布平台About本博客所有文章除特别声明外均采用 CC BY-NC-ND 4.0 许可协议。转载请注明来源 SamHous blog合集: Coding with Grandma

相关新闻

通过Certbot自动申请更新HTTPS网站的SSL证书

通过Certbot自动申请更新HTTPS网站的SSL证书

际憾婪松通过 start.spring.io 或其他构建基础的Spring Boot工程,根据你构建应用的需要增加一些依赖,比如最后用接口提供服务的话,可以加入web模块:org.springframework.bootspring-boot-starter-web2. 注册 UnifiedTTS&#xff0…

2026/7/7 7:30:43 阅读更多 →
面向软件测试从业者的个人信息保护合规审计实战指南

面向软件测试从业者的个人信息保护合规审计实战指南

第一章:第29条核心要求与测试职责定位《个人信息保护法》第29条明确要求个人信息处理者定期进行合规审计,而处理超1000万人信息的机构需每两年至少审计一次。对测试工程师而言,审计不仅是法律义务,更是技术验证过程:测…

2026/7/7 2:45:34 阅读更多 →
Linux VIRT-RES-SHR内存概念理解

Linux VIRT-RES-SHR内存概念理解

僖埔驮换核心动机: 主要动机在于增强现有模型的泛化能力。成熟的协同过滤框架在处理用户行为数据方面非常强大,但本质上依赖于ID的记忆能力,因此在数据稀疏性和物品冷启动问题上存在固有缺陷。引入纯粹基于内容的语义ID,可以为模型提供一个不…

2026/7/7 7:29:58 阅读更多 →

最新新闻

如何利用Wayback Machine浏览器扩展构建你的互联网时光机

如何利用Wayback Machine浏览器扩展构建你的互联网时光机

如何利用Wayback Machine浏览器扩展构建你的互联网时光机 【免费下载链接】wayback-machine-webextension A web browser extension for Chrome, Firefox, Edge, and Safari 14. 项目地址: https://gitcode.com/gh_mirrors/wa/wayback-machine-webextension 在互联网快速…

2026/7/7 7:30:01 阅读更多 →
YOLOv10模型改进-特定领域应用-第92篇:YOLOv10改进策略【特定领域应用】| YOLOv10在安防监控中的应用

YOLOv10模型改进-特定领域应用-第92篇:YOLOv10改进策略【特定领域应用】| YOLOv10在安防监控中的应用

一、本文介绍 本文记录的是YOLOv10在安防监控领域的应用。安防监控需要实时检测人员、车辆、异常行为等目标,YOLOv10凭借其高效的推理速度和准确的检测能力,成为安防监控领域的首选目标检测算法。 二、安防监控场景分析 2.1 检测目标 安防监控场景需要检测的目标包括: 人…

2026/7/7 7:26:00 阅读更多 →
Aimmy完整指南:如何用AI智能瞄准提升你的游戏体验

Aimmy完整指南:如何用AI智能瞄准提升你的游戏体验

Aimmy完整指南:如何用AI智能瞄准提升你的游戏体验 【免费下载链接】Aimmy Universal Second Eye for Gamers with Impairments (Universal AI Aim Aligner (AI Aimbot) - ONNX/YOLOv8 - C#) 项目地址: https://gitcode.com/gh_mirrors/ai/Aimmy 你是否曾在激…

2026/7/7 7:26:00 阅读更多 →
企业申报省级企业技术中心有哪些条件?企业技术中心申报要求详解

企业申报省级企业技术中心有哪些条件?企业技术中心申报要求详解

江苏省省级企业技术中心申报条件主要分为基本准入条件(一票否决项)、核心量化指标、评分与行业系数要求以及合规与前置条件四个维度。具体申报要求如下:一、基本准入条件1.主体资格:企业在江苏省境内注册,具有独立法人…

2026/7/7 7:26:00 阅读更多 →
ASM330LHH与STM32L041C6运动跟踪系统设计与优化

ASM330LHH与STM32L041C6运动跟踪系统设计与优化

1. ASM330LHH与STM32L041C6的硬件组合解析1.1 ASM330LHH的6DoF IMU特性详解ASM330LHH这颗汽车级6轴惯性模块堪称运动跟踪领域的精密仪器。它采用系统级封装(SiP)技术,在3.3mm2.6mm0.83mm的微型封装内集成了三轴数字加速度计和三轴数字陀螺仪。实测中我发现&#xff…

2026/7/7 7:24:00 阅读更多 →
IDM注册表锁定激活技术深度解析:永久试用期管理方案

IDM注册表锁定激活技术深度解析:永久试用期管理方案

IDM注册表锁定激活技术深度解析:永久试用期管理方案 【免费下载链接】IDM-Activation-Script IDM Activation & Trail Reset Script 项目地址: https://gitcode.com/gh_mirrors/id/IDM-Activation-Script Internet Download Manager(IDM&…

2026/7/7 7:21:59 阅读更多 →

日新闻

鸿蒙新特性:图片画廊与轮播导航——构建沉浸式图片浏览体验

鸿蒙新特性:图片画廊与轮播导航——构建沉浸式图片浏览体验

图片浏览是移动应用中最高频的场景之一。从社交应用的照片流到电商平台的商品图集,从旅游应用的景点相册到摄影作品展示——用户对图片浏览的体验要求不断提高:流畅的切换动画、直观的缩略图导航、便捷的收藏操作、自动播放模式。HarmonyOS NEXT ArkUI 虽…

2026/7/7 0:05:16 阅读更多 →
24V DC-DC降压芯片PW2312B/PW2815,SOT23-6到SOP8-EP方案对比

24V DC-DC降压芯片PW2312B/PW2815,SOT23-6到SOP8-EP方案对比

24V稳压芯片完整选型指南 PW8600 PW75XX PW2815 PW2312B LDODC/DC全方案 一、24V稳压方案概述 24V直流电源在工业自动化、门禁系统、电梯控制、汽车电子、LED驱动、监控设备等场景中应用极广,是最常见的中压直流母线电压。要将24V母线稳定降压至下游MCU、传感器…

2026/7/7 0:05:16 阅读更多 →
RAG+知识图谱混合检索与Graph RAG核心对比

RAG+知识图谱混合检索与Graph RAG核心对比

做企业RAG落地的团队,往往容易卡在一容易踩坑的选型难题: 当需求单纯靠向量RAG搞不定、单纯靠知识图谱也搞不定,必须同时依赖「文本语义理解 实体关系推理」时,到底是做「向量图谱混合检索」就够了,还是必须上「Grap…

2026/7/7 0:07:19 阅读更多 →

周新闻

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容 【免费下载链接】BiliTools A cross-platform bilibili toolbox. 跨平台哔哩哔哩工具箱,支持下载视频、番剧等等各类资源 项目地址: https://gitcode.com/GitHub_Trending/bilit/BiliTools …

2026/7/6 8:11:50 阅读更多 →
威胁模型全解析:从新手入门到实战应用,助你构建安全产品!

威胁模型全解析:从新手入门到实战应用,助你构建安全产品!

威胁模型的陌生现状在忙碌疲惫的一天里,参与了关于混合后量子密码学的讨论,应付端点攻击找茬的人,还参与留言板讨论后,发现“威胁模型”对多数人仍是陌生概念,且多被当作时髦用语。有趣的相关画作有一幅由 Embyr 创作的…

2026/7/6 8:11:52 阅读更多 →
渗透测试入门指南:从零基础到实战环境搭建

渗透测试入门指南:从零基础到实战环境搭建

1. 从“看热闹”到“入门”:我理解的渗透测试到底是什么?每次看到新闻里说某个大公司的数据被“黑”了,或者某个网站被攻击导致服务瘫痪,你是不是和我一样,心里会冒出两个念头:一是“这黑客真厉害”&#x…

2026/7/6 6:52:56 阅读更多 →

月新闻