【C++】类型转换 ⑤ ( 常量和非常量之间的类型转换 - 常量类型转换 const_cast | const 左数右指原则 | 代码示例 )

文章目录

  • 一、const 关键字简介
    • 1、const 修饰普通数据
    • 2、const 修饰指针 ( 左数右指原则 | 指针常量 | 常量指针 )
  • 二、常量和非常量 之间的类型转换 - 常量类型转换 const_cast
    • 1、常量类型转换 const_cast
    • 2、常量不能直接修改
    • 3、修改常量值的方法
    • 4、特别注意 - 确保指针指向的空间可修改


在之前写过一篇 C++ 类型转换的博客 【C++ 语言】类型转换 ( 转换操作符 | const_cast | static_cast | dynamic_cast | reinterpret_cast | 字符串转换 ) , 简单介绍了 C++ 类型转换 ;

在 博客 【C++】类型转换 ① ( C 中的类型转换 | C++ 类型转换操作符 | const_cast | static_cast | dynamic_cast | reinterpret_cast ) 将 C 语言 和 C++ 中的类型转换进行了对比 ;

在 博客 【C++】类型转换 ② ( C++ 静态类型转换 static_cast | C 语言隐式转换弊端 | 代码示例 ) 中 , 主要分析了 静态类型转换 static_cast , 可以解决 C 语言隐式转换的弊端 ;

在博客 【C++】类型转换 ③ ( 重新解释类型转换 reinterpret_cast | 指针类型数据转换 ) 分析了 指针数据类型的转换 , 在 C 语言环境下 , 可以使用显示强制类型转换 , 在 C++ 环境中只能使用 重新解释类型转换 reinterpret_cast ;

在博客 【C++】类型转换 ④ ( 子类 和 父类 之间的类型转换 - 动态类型转换 dynamic_cast ) 中 , 分析 C++ 环境下 使用 各种方式 进行 父类 和 子类 类型之间的转换 , 推荐使用 动态类型转换 dynamic_cast ;


本博客中 , 介绍 常量和非常量 之间的类型转换 , C++ 中推荐使用 常量类型转换 const_cast ;





一、const 关键字简介




1、const 修饰普通数据


普通类型数据的常量定义时 , const 关键字 在 数据类型 的 左边 和 右边 其作用 是相同的 ;

    // 下面两种 const 用法效果相同// 定义普通类型 ( 非指针类型 ) 的常量 const 在 类型左右 都是相同的const int a = 10;int const b = 20;

2、const 修饰指针 ( 左数右指原则 | 指针常量 | 常量指针 )


左数右指原则 : 指针 或 数据 的相关常量类型 ;

  • const 在 * 左边 ( 常量指针 | const 修饰的是数据 | 数据是常量不能修改 ) : 如果 const 修饰的是 指针变量 指向的内存空间 ,const char *c , const 修饰的是 char , char 数据不能被修改 , 这是 常量指针 , 指向常量的指针 ;
    • const 关键字在 指针符号 * 左侧 表示该定义的事 常量指针 ( 指向的内存数据不能修改 )
    // 左数右指 : const 在指针左边 数据是常量 , const 在指针右边 指针是常量// 下面两种情况 const 在指针左边 , 数据是常量 , 内存中的数据不能修改//      但是 , c 和 d 指针的指向可以修改// 下面两种情况是相同的const int* c;int const* d;
  • const 在 * 右边 ( 指针常量 | const 修饰的是指针 | 指针是常量不能修改 ) : 如果 const 修饰的是 指针变量 , 如 char * const d , const 修饰的是 char * , 指针不能被修改 ; 这是 指针常量 ;
    • const 关键字在 指针符号 * 右侧是 表示定义的事指针常量 ( 指针本身不能被修改 ) ;
    // 左数右指 : const 在指针左边 数据是常量 , const 在指针右边 指针是常量// 下面的情况 const 在指针右边 , 指针是常量 , 指针地址不能修改 //      但是 , 指针指向的内存中的数据可以修改int* const e = (int*)malloc(10);




二、常量和非常量 之间的类型转换 - 常量类型转换 const_cast




1、常量类型转换 const_cast


const 关键字 既可以修饰 指针 , 又可以修饰 普通类型数据 ;

  • const 修饰 指针 , 遵循左数右指原则 , const 在 * 左侧 数据是常量 不能修改 ( 常量指针 ) , const 在 * 右侧 指针是常量 不能修改 ( 指针常量 ) ;
  • const 修饰的普通常量 , const 在数据类型的左右两侧都可以 ;

常量类型转换 const_cast 可以 将 常量类型 转为 变量类型 , 以及 将 变量类型 转为 常量类型 ;

常量类型转换 const_cast 最大的作用就是 去掉 只读属性 ;


2、常量不能直接修改


函数接收一个 常量字符串 , const char * p 表示修饰的数据是常量 , 指针指向的 字符串 数据不可更改 ;

// const char * p 表示修饰的数据是常量 , 数据不可更改
void fun(const char * p)
{// 直接修改 const char * p 的数据内容会报错p[0] = 'A';
}

上述函数在编译时 , 就会报错 : error C3892: “p”: 不能给常量赋值 ;

已启动生成…
1>------ 已启动生成: 项目: HelloWorld, 配置: Debug Win32 ------
1>Test.cpp
1>D:\002_Project\006_Visual_Studio\HelloWorld\HelloWorld\Test.cpp(8,5): error C3892: “p”: 不能给常量赋值
1>已完成生成项目“HelloWorld.vcxproj”的操作 - 失败。
========== 生成: 成功 0 个,失败 1 个,最新 0 个,跳过 0==========

在这里插入图片描述


3、修改常量值的方法


如果想要在函数中 , 修改常量值 , 可以使用 常量类型转换 const_cast , 先将 常量 转为变量 , 然后再进行修改 ;


在下面的代码中 , const char * p 表示修饰的数据是常量 , 数据不可更改 ;

如果想要修改 常量指针 指向的内存中的数据 ,

要使用 常量类型转换 const_cast , 将 常量指针 改为 变量指针 , 取消 指针指向的 内存空间 的 只读属性 , char* tmp = const_cast<char*>(str) ;

然后可以借助 转换成 变量指针 的 tmp 指针 , 改变指针指向内存中的数据 ;

// const char * p 表示修饰的数据是常量 , 数据不可更改
void fun(const char * str)
{cout << " 函数开始 : " << str << endl;// 直接修改 const char * p 的数据内容会报错// 报错 : error C3892: “p”: 不能给常量赋值//p[0] = 'A';char* tmp = const_cast<char*>(str);tmp[0] = 'A';cout << " 函数结束 : " << str << endl;
}

完整代码示例 :

#include "iostream"
using namespace std;// const char * p 表示修饰的数据是常量 , 数据不可更改
void fun(const char * str)
{cout << " 函数开始 : " << str << endl;// 直接修改 const char * p 的数据内容会报错// 报错 : error C3892: “p”: 不能给常量赋值//p[0] = 'A';char* tmp = const_cast<char*>(str);tmp[0] = 'A';cout << " 函数结束 : " << str << endl;
}int main() {char str[] = "Tom";fun(str);cout << " 程序结束 : " << str << endl;// 控制台暂停 , 按任意键继续向后执行system("pause");return 0;
};

执行结果 :

函数开始 : Tom
函数结束 : Aom
程序结束 : Aom
Press any key to continue . . .

在这里插入图片描述


4、特别注意 - 确保指针指向的空间可修改


使用 常量类型转换 const_cast 时 , 开发者必须确保 指针指向 的空间是可以修改的 , 如果不能修改 , 强行修改 , 会带来未知灾难性的后果 ;


如 : 定义了 字符串常量 , 字符串常量 不会分配内存 , 而是 存储在了 符号表 中 ;

	// 此处直接定义了一个常量字符串// 该常量字符串没有分配内存// 该常量存储在了 符号表 中const char * str = "Tom";

可参考 【C++】C 语言 和 C++ 语言中 const 关键字分析 ( const 关键字左数右指原则 | C 语言中常量的原理和缺陷 | C++ 语言中常量原理 - 符号表存储常量 ) 博客 , 在该博客中详细介绍了 C 语言常量 和 C++ 常量的原理 , C++ 中的常量都是存储在符号表中 , 符号表中的值肯定是不能被修改的 ;

使用 常量类型转换 const_cast , 强行将 符号表中的 常量 转为变量 , 但是 一旦执行 修改操作 , 直接在运行时报错 ;


错误代码示例 :

#include "iostream"
using namespace std;// const char * p 表示修饰的数据是常量 , 数据不可更改
void fun(const char * str)
{cout << " 函数开始 : " << str << endl;// 直接修改 const char * p 的数据内容会报错// 报错 : error C3892: “p”: 不能给常量赋值//p[0] = 'A';char* tmp = const_cast<char*>(str);tmp[0] = 'A';cout << " 函数结束 : " << str << endl;
}int main() {// 此处直接定义了一个常量字符串// 该常量字符串没有分配内存// 该常量存储在了 符号表 中const char * str = "Tom";fun(str);cout << " 程序结束 : " << str << endl;// 控制台暂停 , 按任意键继续向后执行system("pause");return 0;
};

执行结果 : 修改 符号表常量 的那一行代码 , 引发了未知异常 ;

在这里插入图片描述

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

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

相关文章

前后端分离开发出现的跨域问题

先说说什么是跨域。 请求的URL地址中的协议、域名、端口号中的任意一个与当前URL不同就是跨域。 比如&#xff1a; 当前页面的URL请求的URL是否跨域原因htttp://localhost:8080htttps://localhost:8080是协议不同htttp://localhostll:8080htttp://localhost:8080是域名不同htt…

消息队列进阶-1.消息队列的应用场景与选型

&#x1f44f;作者简介&#xff1a;大家好&#xff0c;我是爱吃芝士的土豆倪&#xff0c;24届校招生Java选手&#xff0c;很高兴认识大家&#x1f4d5;系列专栏&#xff1a;Spring源码、JUC源码、Kafka原理&#x1f525;如果感觉博主的文章还不错的话&#xff0c;请&#x1f44…

“2024上海智博会、2024北京智博会”双展联动,3月上海,6月北京

“2024上海智博会、2024北京智博会”双展联动&#xff0c;将分别于3月和6月在上海和北京举办。这两个展会旨在充分展示智慧城市、人工智能、物联网、大数据、软件等新兴行业的最新产品和技术。 作为中国最具影响力和创新力的智能科技展会&#xff0c;上海智博会和北京智博会吸引…

常用的正则表达式

文章目录 一、前言二、语法2.1、简单字符2.2、转义字符2.3、字符集和2.4、量词2.5、字符边界2.6、选择表达式2.7、分组与引用2.8、预搜索2.9、修饰符 三、常用3.1、校验数字的表达式3.2、校验字符的表达式3.3、特殊需求表达式 四、最后 一、前言 正则表达式的语法一般如下js&a…

房屋租赁出售经纪人入驻小程序平台

一款专为房屋中介开发的小程序平台&#xff0c;支持独立部署&#xff0c;源码交付&#xff0c;数据安全无忧。 核心功能&#xff1a;房屋出租、经纪人独立后台、分佣后台、楼盘展示、房型展示、在线咨询、地址位置配套设施展示。 程序已被很多房屋交易中介体验使用过&#x…

XXDD——UUII(交互设计)

今天我们再次回到Adobe全家桶的怀抱&#xff0c;今天介绍的这一位成员&#xff0c;是最直接帮助大家进行平面交互式设计的软件。他就是XD~ Adobe XD全称Adobe Experience Design CC&#xff0c; 官方版跨平台支持Win10 与 macOS&#xff0c;并且所有用户均可免费下载使用。Adob…

物理世界中的等距3D对抗样本

论文题目&#xff1a;Isometric 3D Adversarial Examples in the Physical World 会议&#xff1a;NIPS 2022 点云&#xff1a; 点云——表达目标空间分布和目标表面特性的海量点集合&#xff0c;点包含xyz坐标信息 能够包含颜色等其他信息 使用顶点、边和面的数据表征的三维…

Android Studio导入项目一直显示正在下载Gradle项目

如题&#xff0c;问题图类似如下&#xff1a; &#xff08;此图是解决以后截的&#xff0c;之前遇到问题没截图&#xff09; 解决方法 先找到你正在下载的gradle的版本是哪个 然后在链接中 ​​​​​​Gradle Distributions 找到你所对于gradle的版本&#xff0c;下载对应…

yolov8-seg 分割推理流程

目录 一、分割检测 二、图像预处理 二、推理 三、后处理与可视化 3.1、后处理 3.2、mask可视化 四、完整pytorch代码 一、分割检测 注&#xff1a;本篇只是阐述推理流程&#xff0c;tensorrt实现后续跟进。 yolov8-pose的tensorrt部署代码稍后更新&#xff0c;还是在仓…

mysql主从复制-redis集群扩容缩容、缓存优化(缓存更新策略、穿透,击穿,雪崩)、mysql主从搭建、django实现读写分离

基于Docker实现读写分离 1 redis集群扩容缩容 1.1 集群扩容 1.2 集群缩容 2 缓存优化 2.1 缓存更新策略 2.2 穿透&#xff0c;击穿&#xff0c;雪崩 3 mysql主从搭建 4 django实现读写分离 1 redis集群扩容缩容 1.1 集群扩容 # 6台机器&#xff0c;3个节点集群# 8台机器&am…

java文件上传以及使用阿里云OSS

JavaWeb 文件上传本地存储阿里云OSS配置文件 yml配置文件 文件上传 前端页面三要素&#xff1a; 表单项type“file” 表单提交方式post 表单的enctype属性multipart/form-data 本地存储 保证上传的文件不重复 //获取原始文件名String originalFilename image.getOriginalFi…

【好用的个人工具】在Docker环境下部署Simple mind map思维导图工具

【好用的个人工具】在Docker环境下部署Simple mind map思维导图工具 一、Simple mind map介绍1.1 Simple mind map简介1.2 Simple mind map特点 二、本地环境介绍2.1 本地环境规划2.2 本次实践介绍 三、本地环境检查3.1 检查Docker服务状态3.2 检查Docker版本3.3 检查docker co…