C++威力强大的助手 --- const
Welcome to 9ilk's Code World

(๑•́ ₃ •̀๑) 个人主页: 9ilk
(๑•́ ₃ •̀๑) 文章专栏: C++之旅
const是个奇妙且非比寻常的东西,博主从《Effective C++》一书中认识到关于const更深层次的理解,写此博客进行巩固。
🏠 const的作用
- const可以指定一个“不该被改动的对象”,编译器会强制实施这个约束
- const可修饰类外的作用域(全局域,命名空间域等)中的常量,文件,函数或静态常量等
- const可修饰类内的static和non-static成员
🏠 const修饰指针和迭代器
📌 const修饰指针
const修饰指针无外乎三种:
char greet[] = "hello";
char* pg = greet;//指针指向内容不可变
const char * pg = greet;
char const * pg = greet;//指针本身不可变
char * const pg = greet;//指针本身和指针执行内容都不可变
const char * const pg = greet;
总结:
1.const出现在*号左边时,表示指针指向的内容是常量。
2.const出现在*号右边时,表示指针本身是常量。
3.const出现在*号左右边时,表示指针本身和指针指向的内容都是常量
📌 const与迭代器
- 声明迭代器为const
我们把迭代器看作一个类型,它的作用就像个T*的指针,当声明迭代器为const时,类比const int是int这个int类型变量不可能,此时说明迭代器类型变量是不能变的,也就是类比修饰一个T* const的指针。
vector<int> v = {4,1,2,9,10};
const vector<int>::iterator it = v.begin();it++; //错误,迭代器类型对象不可变
(*it)++; //正确,指向内容可以变
我们也可以利用下面代码进行验证,当生成解决方案时会对其进行报错:
template<class T>
void fun()
{const T x;cout << typeid(x).name() << endl;x++;
}
int main()
{//op o;//cout << o[1];vector<int> v = {3,5};vector<int>::iterator it = v.begin();;fun<vector<int>::iterator>();return 0;
}
- const迭代器
如果你希望迭代器所指的东西不可被改动(也就是类似希望模拟个const T*指针),你需要的是const_iterator.
std::vector<int> v = {1,5,2,3,4};std::vector<int>::const_iterator it = v.begin();*it = 10; //错误,此时是const迭代器,指向内容不可改变。
it++; //此时不是声明迭代器为const,本身迭代器可以改变。
注:我们平时所说的const迭代器就是const_iterator,请注意区分与前者声明迭代器为const进行区分。
🏠 const与函数
📌 const与函数参数
建议:如果对于局部对象或对于函数参数没有改动的需求时,建议将他们声明为const,此时可以避免不必要的麻烦。比如:将“==”键值的“=”。
📌const与函数返回值
- 函数返回一个常量,往往可以降低因客户错误而造成的意外,而且具有安全性和高效性
假设有这样的一个有理数类:
class Rational;const Rational operator*(const Rational& r1,const Rational& r2)
{//...};Rational a,b,c;
...
(a*b) = c;
由于是有理数类,客户可能会将乘积再做一次赋值,此时将operator*的返回值类型设置为const就可以避免这样无意义的赋值动作。
🏠 const与成员函数
📌 const成员函数的好处
1. const成员函数易使class接口比较容易被理解,清楚知道哪个函数可以改动对象内容而哪个函数不行。
2. 有了const成员函数,const对象就能被“操作”,因为const对象只能调用const成员函数;能操作const对象,就能利用传引用(const 类类型 &)提高效率。
- const成员函数与普通成员函数的区别
我们知道普通成员函数参数都有一个隐含的this指针,是不能修改的,也就是类 * const this;而const成员函数的this指针,类型是const 类 * const this,也就是说此时对象的内容也不能被修改。
class Date
{
public:
//... const char& operator[](size_t position)const //operator[]for const对象{return _date[position];}char& operator[](size_t position) //operator[]for non-const 对象{return _date[position];}private:string _date;};int main()
{Date d1("2024/08/04");cout << d1[0] << endl; //调用的是non-const版本const Date d2("2024/08/04")cout << d2[0]; //调用的是const版本return 0;
}
- 说明
1. 两成员函数如果只是常量性不同,也是可以被重载的。因为两个版本隐含的this类型不同,同时
返回值类型也跟着不同。
2.const对象d2的对象指针为const Date* ,更匹配const版本的operator[],因此调用const版本;
而非const对象d1的对象指针为Date*,更匹配非const版本。
📌 bitwise const VS logical const
到这里,我们思考一下什么成员函数如果是const意味着什么?目前有以下两个流行概念需要向大家介绍一下:
- bitwise constness
这种观点的人认为,成员函数只有在不改变对象之任何成员变量时才可以说是const,也就是说不改变对象内的任何一个bit。这种论点的好处是很容易找到违反点:只需找到对成员变量的赋值动作即可。
这种观点正是C++对常量性的定义,因此const成员函数不可以更改对象内任何非静态成员变量。
如果只有指针(而非所指向内容)隶属于对象,(比如有这样的一个类,将数据存储于char*而不是string),不修改char*而修改char*指向内容,此时编译器是认为是bitwise constness的,可以正常通过编译。
class Block
{
public:Block( char* ch ):pText(ch){}char& operator[](size_t position)const{return pText[position];}private:char* pText;
};int main()
{char arr[] = "hello";char* ch = arr;const Block cctb(ch);char* pc = &cctb[0];*pc = 's';return 0;
}
此时可以通过这个漏洞修改成员变量指针指向的内容而不违法const
(注:如果成员变量是string,由于operator[]需要访问pText成员变量,并且你需要保证Block对象的状态不被修改,所以pText的operator[]调用也必须是const的,因此不会出现上述漏洞。)
这种情况导出所谓的logical constness.
- logical constness
class BigArray
{vector<int> v; int accessCounter;
public:int getItem(int index) const { accessCounter++;return v[index];}
};
此类提供了一个
getItem接口,除此之外,为了计算外部访问数组的次数,该类还设置了一个计数器accessCounter,可以看到用户每次调用getItem接口,accessCounter就会自增,很明显,这里的成员v是核心成员,而accessCounter是非核心成员。
我们希望接口 getItem 不会修改核心成员,而不考虑非核心成员是否被修改,此时 getItem 所具备的 const 特性就被称为 logic constness。
问题:在这个函数中虽然accesCounter修改对对象而言可以被接受,但是编译器只认bitwise constness不允许修改怎么办?
- mutable
mutable是C++中一个与const相关的摆动场,他可以释放掉non-static成员变量的bitwise constness约束。
class BigArray {vector<int> v; mutable int accessCounter; //像这样的成员变量可能总是会被更改。
public:int getItem(int index) const { accessCounter++;return v[index];}
};
总结:当const成员函数接受某些修改之后不改变成员函数逻辑状态的成员变量时,这时可以使用mutable来释放const约束。但注意mutable可能会违反对象的不变性,需要慎用。
📌 在const和non-const成员函数中避免重复
对于“bitwise constness”非我所欲的问题,mutable是个解决办法,但并不能解决所有的难题。假设有个类,类内的operator[ ]不单只是返回一个引用指向某字符,也执行边界检验,志记访问信息,甚至可能进行数据完善性检验等...把所有这些放进const版本和非const版本的operator[ 里的问题是会导致代码膨胀以及大量代码重复:
class Text
{public:char& operator[](size_t pos){//... 边界检验//... 志记数据访问//... 检验数据完整性return text[pos];}const char& operator[](size_t pos)const{//... 边界检验//... 志记数据访问//... 检验数据完整性return text[pos];}private:string text;};
避免代码重复的安全做法:
class Text
{public:const char& operator[](size_t pos){//... 边界检验//... 志记数据访问//... 检验数据完整性return text[pos];}char& operator[](size_t pos)const{return (char&)(((const Text &)(*this))[pos]);}private:string text;};
- 说明
1. 这份代码进行了两次转型实现了了“运用const成员函数实现其non-const兄弟”,避免了代码重
复。
2.第一次转型将(*this)也就是这个对象类型强转为const Text&是为了匹配const版本调用const版
本的operator[ ],否则会陷入无限调用非const版本;第二次转型则是用来从const operator[ ]的
返回值中移除const,这其中并未有权限放大的问题,强转是可行的。
3. 反向调用也就是“令const版本调用non-const版本以避免代码重复”是一件错误的事,因为non-
const并未承诺绝不改变其对象的逻辑状态,因此这种做法可能使得对象被改动,当然编译器也不
允许const调用非const,也是一种权限的放大。
总结:
1. 将某些东西声明为const可帮助编译器侦测出错误用法,比如错误的赋值行为使得不必要的对象改动。
2.const可施加于任何作用域的对象,函数参数,函数返回值,成员函数。
3.如果在const成员函数内想改变非核心成员变量以达目的,可利用mutable解除const约束。
4.当const与非const成员函数实质有着等价的实现且代码有大量重复时,可考虑复用const版本以实现非const版本。
相关文章:
C++威力强大的助手 --- const
Welcome to 9ilks Code World (๑•́ ₃ •̀๑) 个人主页: 9ilk (๑•́ ₃ •̀๑) 文章专栏: C之旅 const是个奇妙且非比寻常的东西,博主从《Effective C》一书中认识到关于const更深层次的理解,写此博客进行巩固。 &#x…...
测试环境搭建整套大数据系统(十八:ubuntu镜像源进行更新)
镜像源更新为清华源 报错显示 解决方案 做好备份 cp /etc/apt/sources.list /etc/apt/sources.list.bak查看配置信息 sudo vim /etc/apt/sources.listsudo sed -i s/cn.archive.ubuntu.com/mirrors.aliyun.com/g /etc/apt/sources.list sudo apt update...
第128天:内网安全-横向移动IPCATSC 命令Impacket 套件CS 插件全自动
环境部署 案例一: 域横向移动-IPC-命令版-at&schtasks 首先是通过外网web访问到win2008,获得了win2008的权限,这一步不做演示 因为里面的主机都不出网,所以只能利用win2008进行正向或者反向连接 信息收集 域内用户信息&…...
记录一次学习过程(msf、cs的使用、横向渗透等等)
目录 用python搭建一个简单的web服务器 代码解释 MSF msfvenom 功能 用途 查看payloads列表 msfconsole 功能 用途 msfvenom和msfconsole配合使用 来个例子 msf会话中用到的一些命令 在windows中net user用法 列出所有用户账户 显示单个用户账户信息 创建用户账…...
C#中DataTable新增列、删除列、更改列名、交换列位置
C#中DataTable新增列、删除列、更改列名、交换列位置 一、新增列 1.1、新增列 /*新增列*/ dataTable.Columns.Add("列名称", Type.GetType("数据类型")); /*比如添加【name】列,string类型的内容*/ dataTable.Columns.Add("name&…...
C#编写多导联扫描式的波形图Demo
本代码调用ZedGraph绘图框架,自己先安装好ZedGraph环境,然后拖一个zedGraphControl控件就行了,直接黏贴下面代码 基本代码显示 using System; using System.Windows.Forms; using ZedGraph; using System.Timers;namespace ECGPlot {public…...
QT网络编程
Qt 给用户提供了网络编程的接口,包括TCP、UDP、HTTP三种协议的API以及各种类,可以了解一下。 而在 QT 中想要使用网络编程,必须在pro文件中添加 network 模块,否则无法包含网络编程所需的头文件。 UDP UDP是传输层的协议&#…...
Django ASGI服务
1. ASGI简介 在Django中, ASGI(Asynchronous Server Gateway Interface)的引入使得Django应用能够支持异步编程. 从Django 3.0开始, Django就增加了对ASGI的支持, 但直到Django 3.1才正式推荐在生产环境中使用ASGI. ASGI是一个用于Python的异步Web服务器的标准接口, 它允许你运…...
Servlet(2)
1、WebServlet 这个注解可以用来修饰一个Servlet类,可以简化配置,替代Web.xml中 的servlet配置 ①value属性 表示指定某个url-pattern ②urlPatterns属性 表示接受多个不同的url-pattern,多个值写在一对{}中,逗号分隔 补充;url-pattern…...
电竞玩家的云端盛宴!四大云电脑平台:ToDesk、顺网云、青椒云、极云普惠云实测大比拼
本文目录 一、云电脑概念及市场需求二、云电竞性能测试2.1 ToDesk云电脑2.2 顺网云2.3 青椒云2.4 极云普惠云电脑 三、四大云电脑平台综合配置对比3.1 CPU处理器3.2 GPU显卡3.3 内存 四、总结 一、云电脑概念及市场需求 在数字化时代的推动下,云计算技术日益成熟&a…...
基础复习(反射、注解、动态代理)
反射 反射,指的是加载类的字节码到内存,并以编程的方法解刨出类中的各个成分(成员变量、方法、构造器等)。 1.获取类的字节码 (3种方式) public class Test1Class{public static void main(String[] arg…...
OGG同步目标端中文乱码处理
现象说明: 源端字符集:AMERICAN_AMERICA.ZHS16GBK 目标端字符集:AMERICAN_AMERICA.AL32UTF8 源端同步过来的数据显示中文乱码。 查询数据库表中含有乱码的字段: select * from xx.xxxx a where to_char(a.crtopetime,yyyy-mm-…...
使用WPF调用Python进行图像灰度处理
1. 前言 在本文中,我们将通过WPF应用程序调用Python脚本进行图像灰度处理。我们将使用Python的OpenCV库来处理图像,并将其转换为灰度图像,然后通过WPF界面来启动Python进程并展示结果。 2. 准备工作 在开始之前,请确保系统已经…...
(二)测试工具
16. 如何进行浏览器兼容性测试? 正确回答通过率:38.0%[ 详情 ] 推荐指数: ★★★★★ 试题难度: 高难 1、兼容性测试含义 兼容性测试是指要测试的软件在不同的硬件平台上、不同的应用软件之间、不同的操作系统中、不同的网络环境中是否可以正常的运行、有无异常的测试过程…...
springboot 博客交流平台-计算机毕业设计源码56406
摘要 博客交流平台 作为一种重要的网络平台,为用户提供了展示自我、分享经验和与他人互动的空间。在国内外,研究者们关注博客交流平台 的各个方面,并取得了显著的进展。研究内容主要包括用户体验和界面设计、社交化和互动性、多媒体内容支持、…...
从0开始搭建vue + flask 旅游景点数据分析系统( 八):美化前端可视化图形
这一期来美化我们仅有的三个可视化图形(可怜),毕竟,帅是一辈子的事。 1 折线图改面积图(渐变色) 需求:折线图改为蓝色的面积图,并且有一点的渐变色。 这个非常简单,只…...
【前端面试】七、算法-迭代器和生成器
目录 1.迭代器 2.生成器 1.迭代器 lterator:也被称作游标Cursor,是一种设计模式。迭代器提供了一种遍历内容的方法(比如 JS 迭代器中的next),而不需要关心内部构造。 // 迭代器的遍历const s new Set([1,2,3,4,5])const it s.values()//…...
vs+qt一些问题
一直遇到的两个问题,今天解决了 1、 因为前后端分离,前端写完了,后端还在一直修改,但是每次都是单独打开的后端的sln,所以会出现这个,把前端的模块删掉就好了。 2、打开vs项目,很多报错&#…...
基于K8S配置Jenkins主从节点实例
基于K8S配置Jenkins主从节点实例 1.配置Jenkins主节点1.确认 Jenkins Pod 名称2.进入 Jenkins Pod:3.生成SSH密钥对4.将公钥复制到目标节点: 2.配置Jenkins的node1节点1.安装java2.配置 Jenkins node1节点的 Java 路径1.添加Java环境变量2.生效Java环境变…...
萱仔环境记录——git的安装流程
最近由于我有一个大模型的offer,由于我只在实验室的电脑上装了git,我准备在自己的笔记本上本地安装一个git,也给我的一个师弟讲解一下git安装和使用的过程,给我的环境安装章节添砖加瓦。 github是基于git的一个仓库托管平台。 g…...
接口测试中缓存处理策略
在接口测试中,缓存处理策略是一个关键环节,直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性,避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明: 一、缓存处理的核…...
OpenLayers 可视化之热力图
注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 热力图(Heatmap)又叫热点图,是一种通过特殊高亮显示事物密度分布、变化趋势的数据可视化技术。采用颜色的深浅来显示…...
Linux 文件类型,目录与路径,文件与目录管理
文件类型 后面的字符表示文件类型标志 普通文件:-(纯文本文件,二进制文件,数据格式文件) 如文本文件、图片、程序文件等。 目录文件:d(directory) 用来存放其他文件或子目录。 设备…...
电脑插入多块移动硬盘后经常出现卡顿和蓝屏
当电脑在插入多块移动硬盘后频繁出现卡顿和蓝屏问题时,可能涉及硬件资源冲突、驱动兼容性、供电不足或系统设置等多方面原因。以下是逐步排查和解决方案: 1. 检查电源供电问题 问题原因:多块移动硬盘同时运行可能导致USB接口供电不足&#x…...
Python实现prophet 理论及参数优化
文章目录 Prophet理论及模型参数介绍Python代码完整实现prophet 添加外部数据进行模型优化 之前初步学习prophet的时候,写过一篇简单实现,后期随着对该模型的深入研究,本次记录涉及到prophet 的公式以及参数调优,从公式可以更直观…...
Qt Http Server模块功能及架构
Qt Http Server 是 Qt 6.0 中引入的一个新模块,它提供了一个轻量级的 HTTP 服务器实现,主要用于构建基于 HTTP 的应用程序和服务。 功能介绍: 主要功能 HTTP服务器功能: 支持 HTTP/1.1 协议 简单的请求/响应处理模型 支持 GET…...
【2025年】解决Burpsuite抓不到https包的问题
环境:windows11 burpsuite:2025.5 在抓取https网站时,burpsuite抓取不到https数据包,只显示: 解决该问题只需如下三个步骤: 1、浏览器中访问 http://burp 2、下载 CA certificate 证书 3、在设置--隐私与安全--…...
微信小程序云开发平台MySQL的连接方式
注:微信小程序云开发平台指的是腾讯云开发 先给结论:微信小程序云开发平台的MySQL,无法通过获取数据库连接信息的方式进行连接,连接只能通过云开发的SDK连接,具体要参考官方文档: 为什么? 因为…...
Spring AI与Spring Modulith核心技术解析
Spring AI核心架构解析 Spring AI(https://spring.io/projects/spring-ai)作为Spring生态中的AI集成框架,其核心设计理念是通过模块化架构降低AI应用的开发复杂度。与Python生态中的LangChain/LlamaIndex等工具类似,但特别为多语…...
均衡后的SNRSINR
本文主要摘自参考文献中的前两篇,相关文献中经常会出现MIMO检测后的SINR不过一直没有找到相关数学推到过程,其中文献[1]中给出了相关原理在此仅做记录。 1. 系统模型 复信道模型 n t n_t nt 根发送天线, n r n_r nr 根接收天线的 MIMO 系…...
