【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.mzph.cn/news/180135.shtml

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

相关文章

【离散数学】——期末刷题题库(命题逻辑)

&#x1f383;个人专栏&#xff1a; &#x1f42c; 算法设计与分析&#xff1a;算法设计与分析_IT闫的博客-CSDN博客 &#x1f433;Java基础&#xff1a;Java基础_IT闫的博客-CSDN博客 &#x1f40b;c语言&#xff1a;c语言_IT闫的博客-CSDN博客 &#x1f41f;MySQL&#xff1a…

在CI/CD中使用submodule

背景信息 客户的submodule使用的是ssh协议拉取 前置操作 gitlab添加子模块 git clone ssh://gitkube.bdeet.top:2222/cicd/123.git cd 123/ ls -la git submodule add ssh://gitkube.bdeet.top:2222/approve/test-1.git git submodule add ssh://gitkube.bdeet.top:2222/mr…

java三大集合类--List

List Set Map 一、List 几个小问题&#xff1a; 1、接口可以被继承吗&#xff1f;&#xff08;可以&#xff09; 2、接口可以被多个类实现吗&#xff1f;&#xff08;可以&#xff09; 3、以下两种写法有什么区别&#xff1f; //List list1new List();是错误的因为List()…

数据治理技术:研究现状与数据规范

随着信息技术的迅速发展,数据规模逐渐扩大&#xff0c;与此同时&#xff0c;劣质数据也随之而来&#xff0c;极大地降低了数据挖掘的质量&#xff0c;对信息社会造成了严重的困扰&#xff0c;劣质数据大量存在于很多领域和机构&#xff0c;国外权威机构的统计表明&#xff1a;美…

Android : 异常记录

查询大数据时 报错 android.database.sqlite.SQLiteBlobTooBigException: Row too big to fit into CursorWindow requiredPos0, totalRows1解决办法&#xff1a;cursor DB.rawQuery("select * from " DBhelpUtil.TABLE_NAME" where id ?",new String[]…

untiy 配置iis服务器来打开webgl

最简单的方法是不需要配置服务器&#xff0c;打包的时候直接build and run&#xff0c;但是有时候如果我们需要调整js的内容&#xff0c;会很不方便&#xff0c;所以配置一个iis服务器还是很有必要的 首先要开启iis服务 控制面板&#xff0c;查看方式选类型&#xff0c;点击程…

C++设计模式——工厂模式 :简单工厂、工厂方法、抽象工厂

工厂模式可以分为三种&#xff0c;简单工厂模式&#xff0c;工厂方法模式和抽象工厂模式。 那么&#xff0c;这三种工厂模式长啥样&#xff0c;又为啥会衍生出这三种模式来呢&#xff1f;本篇和大家一起来学习总结一下。 一、简单工厂模式 简单工厂SimpleFactory 负责创建所有…

Webpack——模块打包

模块之于程序&#xff0c;就如同细胞之于生物体&#xff0c;是具有特定功能的组成单元。不同的模块负责不同的工作&#xff0c;它们以某种方式联系在一起&#xff0c;共同保证程序的正常运转。介绍Webpack如何对其进行打包以及合并&#xff0c;主要内容如下&#xff1a; 不同模…

使用OSS搭建私有云内网yum仓库的方法

使用OSS搭建私有云内网yum仓库的方法 文字&图片内容已脱敏 #、前几天接到一个搭建内网yum源的任务。刚接到这个任务的时候还是比较头疼的&#xff0c;因为内部有很多VPC。VPC与VPC之间是不互通的&#xff0c;又不能打高速通道&#xff0c;也不可能每个VPC下边都建一个yum…

Python 判断域名是否合规且是否可访问

需求 获得参数为域名的字符串后 1. 判定是否为合规域名 2. 该域名是否活着&#xff08;可访问&#xff09; 实例 headers { # 默认标头User-Agent: $,Accept: text/html,application/xhtmlxml,application/xml;q0.9,*/*;q0.8,Accept-Language: en-US,en;q0.5,Accept-Enc…

csv文件EXCEL默认打开乱码问题

这里讨论的问题是&#xff0c;当用记事本打开带有中文字符的csv正常时&#xff0c;用excel打开却是乱码。 简单概括就是&#xff1a;编码问题&#xff0c;windows的 excel打开csv文本文件时&#xff0c;默认使用的是系统内的ANSI&#xff0c;在中文环境下就是GB2312。如果写文件…

mySQL踩坑记录

1.MYSQL Workbench-8.0.27.1出现"Exception: Current profile has no WMI enabled"错误的解决方法 MYSQL Workbench-8.0.27.1出现“Exception: Current profile has no WMI enabled“错误的解决方法_赛风扥的博客-CSDN博客 C:\Program Files\MySQL\MySQL Workbench …

windows11 phpstudy_pro php8.2 安装redis扩展

环境&#xff1a;windows11 phpstudy_pro php8.2.9 一、命令查看是否安装redis扩展 在对应网站中通过打开&#xff0c;&#xff0c;选择对应的PHP版本&#xff0c;用命令 php -m 查看自己的php 有没有redis扩展 上面如果有&#xff0c;说明已经安装了,如果没有安装&#xff1…

AWL中英文对照表

Sublist 1 sector&#xff1a;部门、 available&#xff1a;可用的、 financial&#xff1a;财务的、 process&#xff1a;过程、 individual&#xff1a;个人的、 specific&#xff1a;具体的、 principle&#xff1a;原则、 estimate&#xff1a;估计、 variables&#xff1…

5 时间序列预测入门:LSTM+Transformer

0 引言 论文地址&#xff1a;https://arxiv.org/abs/1706.03762 1 Transformer Transformer 模型是一种用于处理序列数据的深度学习模型&#xff0c;主要用于解决自然语言处理&#xff08;NLP&#xff09;任务。它在许多 NLP 任务中取得了重大突破&#xff0c;如机器翻译、文本…

docker安装elasticsearch

1、拉取镜像 docker pull elasticsearch:7.17.5 (听说这玩意不同版本有不同的坑&#xff0c;不兼容程序等等&#xff0c;所以要注意下载对应版本号) 2、创建挂载目录 mkdir -p /mydata/elasticsearch/config mkdir -p /mydata/elasticsearch/data echo "http.host: …

Linux内存管理(六十四):ION 内存管理器——system heap

源码基于:Linux 5.4 约定: 芯片架构:ARM64内存架构:UMACONFIG_ARM64_VA_BITS:39CONFIG_ARM64_PAGE_SHIFT:12CONFIG_PGTABLE_LEVELS :30. 前言 ION 是 Google 在 Android 4.0 中引入,目的主要是通过在硬件设备和用户空间之间分配和共享内存,实现设备之间零拷贝共享内存…

Servlet-Vue-JSON交互

Servlet-Vue-JSON交互 统一结果返回 定义 package org.example.result;import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor;Data NoArgsConstructor AllArgsConstructor public class Result<T> {private Integer code;private St…

Android Studio 模拟器设置独立窗口

目录 模拟器在窗口内部运行 设置成独立窗口 模拟器在窗口内部运行 操作起来十分不便 设置成独立窗口 Android Studio -> Preferences(Settings) -> Tools-> Emulator ->取消勾选 Launch in a tool window -> 点击右下角的 OK 按钮 -> 重启 Android Studio

Python与微信交互(互动)神器yyds

Weixin-Python 是一个用于开发微信公众平台应用的 Python 库。它可以帮助你轻松地处理微信服务器发来的消息&#xff0c;以及向用户发送各种类型的消息。 Weixin-Python 的主要功能包括&#xff1a; 验证微信服务器的签名&#xff0c;确保请求来自微信服务器。解析微信服务器发…