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

news2024/11/25 20:17:59

文章目录

  • 一、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.coloradmin.cn/o/1265145.html

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

相关文章

webpack具体实现--未完

1、前端模块打包工具webpack webpack 是 Webpack 的核心模块&#xff0c;webpack-cli 是 Webpack 的 CLI 程序&#xff0c;用来在命令行中调用 Webpack。webpack-cli 所提供的 CLI 程序就会出现在 node_modules/.bin 目录当中&#xff0c;我们可以通过 npx 快速找到 CLI 并运行…

视频字幕处理+AI绘画,Runway 全功能超详细使用教程(4)

runway的视频字幕处理、AI绘图功能介绍&#xff0c;感觉完全就是为了做电影而布局&#xff0c;一整套功能都上线了&#xff01;想系统学习的必收藏&#xff01; 在深度研究Runway各个功能后&#xff0c;无论是AI视频生成及后期处理技术&#xff0c;还是AI图像生成技术&#xff…

企业级开发链表思路

项目结构 头文件代码 头文件代码LinkList.h #ifndef LINKLIST_H #define LINKLIST_H #include <stdio.h> #include <stdlib.h> #include <iostream> // 链表小节点 typedef struct LINKBODE {struct LINKBODE* next;}LinkNode; // 遍历的函数指针 typedef …

纯cpp如何模拟qt的信号与槽

纯cpp如何模拟qt的信号与槽 我之前是如何使用bind的?一.demo示例二.简单来讲,c自带的bind与function函数,如何实现类似信号与槽的机制1. 简单语法2. function与bind联动尝试1尝试2真正实现流程图 自我反思 我之前是如何使用bind的? 一.demo示例 using MsgHander std::funct…

使用elasticsearch-head插件修改elasticsearch数据

1、先使用elasticsearch-head插件基本查询功能找到要修改的数据&#xff0c;看看是否存在 2、切换到elasticsearch-head复合查询界面&#xff0c;输入数据修改地址&#xff1a; http://es的ip地址:端口号/索引名称/文档类型&#xff08;没特殊设置过就是_doc&#xff09;/文档…

springboot 自定义starter逐级抽取

自定义starter 背景:各个组件需要引入starter 还有自己的配置风格 –基本配置原理 &#xff08;1&#xff09;自定义配置文件 导入配置可以在配置文件中自动识别&#xff0c;提示 导入依赖后可以发现提示 &#xff08;2&#xff09;配置文件实现 –让配置文件对其他模块生…

15.Docker-Compose的概念理解及安装

1.Docker-Compose是什么&#xff1f; Docker-Compose是实现对Docker容器集群的快速编排的工具软件。它是Docker官方开源的一个工具软件&#xff0c;可以管理多个Docker容器组成一个应用。你需要定义一个YAML格式的配置文件docker-compose.yml.写好多个容器间的调用关系&#x…

父进程隐藏——ConsoleApplication903项目

首先我发现用calc来做进程隐藏实验是失败的&#xff0c;父进程一直都是svhost.exe 那么我用我自己生成的cs木马beacon903.exe试试 试试explorer.exe 再试试cmd.exe 可以看到成功变成cmd.exe 可以看到我们可以通过这种方式虚假父进程 以上我们是直接获得的pid&#xff0c;那…

使用shell快速查看电脑曾经连接过的WiFi密码

此方法只能查看以前连接过的wifi名称和对应的密码 查看连接过的WiFi名称netsh wlan show profiles查看具体的WiFi名称netsh wlan show profile name"你的wifi名称" keyclear

万宾科技可燃气体监测仪科技作用全览

燃气管网在运行过程中经常会遇到燃气管道泄漏的问题&#xff0c;燃气泄漏甚至会引起爆炸&#xff0c;从而威胁人民的生命和财产安全&#xff0c;因此对燃气管网进行定期巡检是十分必要的工作。但是传统的人工巡检已不能满足城市的需要&#xff0c;除了选择增加巡检人员之外&…

ssm购物商城系统

摘 要 网络技术和计算机技术发展至今&#xff0c;已经拥有了深厚的理论基础&#xff0c;并在现实中进行了充分运用&#xff0c;尤其是基于计算机运行的软件更是受到各界的关注。加上现在人们已经步入信息时代&#xff0c;所以对于信息的宣传和管理就很关键。因此商城购物信息的…

WordPress插件大全-免费的WordPress插件汇总

随着互联网的不断发展&#xff0c;网站建设变得日益普及。对于大多数人而言&#xff0c;WordPress是一个熟悉且易于使用的网站建设平台。然而&#xff0c;有时候我们可能会觉得WordPress的功能还不够满足我们的需求&#xff0c;这时候&#xff0c;插件就成了解决问题的得力工具…

js数组map()的用法

JavaScript Array map() 方法 先说说这个方法浏览器的支持&#xff1a; 支持五大主流的浏览器&#xff0c; 特别注意&#xff1a;IE 9 以下的浏览器不支持&#xff0c;只支持IE 9以上的版本的浏览器 特别注意&#xff1a;IE 9 以下的浏览器不支持&#xff0c;只支持IE 9以上的…

<JavaDS> 二叉树遍历各种遍历方式的代码实现 -- 前序、中序、后序、层序遍历

目录 有以下二叉树&#xff1a; 一、递归 1.1 前序遍历-递归 1.2 中序遍历-递归 1.3 后序遍历-递归 二、递归--使用链表 2.1 前序遍历-递归-返回链表 2.2 中序遍历-递归-返回链表 2.3 后序遍历-递归-返回链表 三、迭代--使用栈 3.1 前序遍历-迭代-使用栈 3.2 中序遍…

flask web开发学习之初识flask(一)

一、概念 flask是一个使用python编写的轻量级web框架&#xff0c;作者为Armin Ronacher&#xff08;中文名&#xff1a;阿尔敏罗纳彻&#xff09;&#xff0c;它广泛被应用于web开发和API。flask提供了简洁而灵活地方式来构建web应用&#xff0c;它不会强加太多约束&#xff0…

docker安装Sentinel zipkin

文章目录 引言I Sentinel安装1.1 运行容器1.2 DOCKERFILE 参考1.3 pom 依赖1.4 .yml配置(整合springboot)II 资源保护2.1 Feign整合Sentinel2.2 CommonExceptionAdvice:限流异常处理类III zipkin引言 消息服务和请求第三方服务可不配置Sentinel。 I Sentinel安装 Sentinel …

智能优化算法应用:基于人工蜂群算法无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于人工蜂群算法无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于人工蜂群算法无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.人工蜂群算法4.实验参数设定5.算法结果6.参考…

玻色量子真机测试完整报告

​ 真机测试 2023年 2023.8 量子计算突破云渲染资源调度&#xff01;真机测试完整报告公开&#xff01; 2023.8 量子计算突破金融信用评分&#xff01;真机测试完整报告公开&#xff01; 组合优化问题专题 2023年 2023.7 玻色量子“揭秘”之旅行商问题与Ising建模 2023.…

食谱菜谱大全API接口

食谱菜谱大全API接口 一、食谱菜谱大全API接口二、使用步骤1、接口2、请求参数3、请求参数示例4、接口 返回示例 三、 如何获取appKey和uid1、申请appKey:2、获取appKey和uid 四、重要说明 一、食谱菜谱大全API接口 包含所有家用或者商用的食谱菜谱的API接口 二、使用步骤 1…

MySQL索引使用总结

索引(index) 官方定义&#xff1a;一种提高MySQL查询效率的数据结构 优点&#xff1a;加快查询速度 缺点&#xff1a; 1.维护索引需要消耗数据库资源 2.索引需要占用磁盘空间 3.增删改的时候会影响性能 索引分类 索引和数据库表的存储引擎有关&#xff0c;不同的存储引擎&am…