C++中的类型转换操作符:static_cast reinterpret_cast const_cast dynamic_cast
目录
C语言中的类型转换
C++中的类型转换
C++中的类型转换操作符
static_cast
reinterpret_cast
const_cast
volatile关键字
赋值兼容
dynamic_cast
C语言中的类型转换
基本概念:赋值运算符左右两侧类型不同,或形参与实参类型不匹配,或者返回值类型与接收返回值类型不一致时,需要发生类项转换,C语言中有两种形式的类型转换,隐式类型转换和显示类型转换
注意事项:有关联的类型才可以相互转换,小类型会转换为大类型
- 整型之间的隐转(int、long、short)
- 整型和浮点数间的隐转
- 整型和字符型间的隐转
- bool和整型、指针间的隐转(整数0和空指针均表示假)
- 整型和指针间的强转(地址的本质是一个编号所以可以)
//整型转换为指针
//缺点:在绝大多数情况下是不安全的,除非你确切知道这个整数表示的内存地址是有效的
int number = 1234;
int *ptr = (int *)number;//指针转换为整型:通常用于获取指针的内存地址
//缺点:如果在64位系统上,将指针转换为32位整数(如 int),可能会导致数据丢失。因此,建议使用 intptr_t 或 uintptr_t 类型,它们在 <stdint.h> 头文件中定义,可以确保适当的大小来存储指针值
int *ptr = &number;
int address = (int)ptr;
关于intptr_t和uintptr_t可以查看:intptr_t、uintptr_t数据类型的解析
- 不同类型的指针间的强转
//不同类型的指针间的强制类型转换
char s = 'a';
char* ptr1 = &s;
int* ptr2 = (int*) ptr1;
显示类型转换的缺点:
- 可能导致数据丢失:当从一个较大的数据类型转换为一个较小的数据类型时,可能会丢失数据。例如,将 double 转换为 int 时,小数部分会被截断
double d = 3.14; int i = (int)d; // i = 3, 小数部分丢失
- 降低代码可读性:频繁使用显式类型转换会使代码变得难以阅读和理解,尤其是当类型转换逻辑复杂时
float f = (float)((int)doubleValue * 2.0);
- 增加错误风险:进行类型转换时,容易忽略一些潜在的错误,如溢出或数据精度问题,导致难以发现的bug
long longValue = 1234567890123456789LL;
int intValue = (int)longValue; // 可能会溢出
隐式类型转换的缺点:
-
隐蔽的数据丢失:将
int
转换为float
时,如果整数的值超过了浮点数的精度范围,可能会丢失精度
int i = 123456789; float f = i; // 可能会丢失精度
-
难以调试和维护:隐式类型转换发生在幕后,可能导致意外的结果和难以调试的问题。出错时需要仔细检查代码,以确保所有隐式转换都符合预期
//int被转换为size_t,当传入的pos = 0时,会陷入死循环
void Insert(size_t pos)
{int end = 10;// 比较的时候end会隐式类型转换成size_t,再比较while (end >= pos){cout << end << "挪走" << endl;--end;}
}
C++中的类型转换
基本概念:C++中通过构造函数和重载可以实现内置类型与自定义类型间、自定义类型间的转换
- 内置类型->自定义类型:借助构造函数,隐式类型转换
//单参数的构造函数,支持内置类型隐式转换成自定义类型
string s1 = "111111";
const string& s2 = "11111";
- 自定义类型->内置类型:重载某个类型(operator +类型名)
class A
{
public:operator int(){return _a1 + _a2;}
private:int _a1 = 1;int _a2 = 2;
};int main()
{A aa;int a = aa;int b = (int)aa;cout << a << endl;cout << b << endl;return 0;
}
- 自定义类型->自定义类型:借助构造函数进行隐式类型转换(initializer_list和容器间)
C++中的类型转换操作符
基本概念:C++依然兼容C语言的两种类型转换方式,但是为了加强类型转换时的可视性,C++引入了四种类型转换操作符,它们是一些进行类型转换时的命名建议,并不强制
static_cast
基本概念:进行有关联的类型间的隐式类型转换(编译时进行,也叫静态转换)
int main()
{//C++的隐式类型转换:明显double d = 12.34;int a1 = static_cast<int>(d);cout << a1 << endl;//12//C语言的隐式类型转换:不明显int a2 = d;cout << a2 << endl;//12return 0;
}
reinterpret_cast
音标:riːɪnˈtɜːrprət
基本概念:进行强制类型转换,不进行类型检查
int main()
{int a = 12;// int* p = static_cast<int*>(a); 报错,int和int*不是两个相关的类型int* p = reinterpret_cast<int*>(a);cout << p << endl;return 0;
}
const_cast
基本概念:删除对象的const属性
int main()
{const int a = 10;int* p = const_cast<int*>(&a); // 去除const属性*p = 20; // 尝试修改值cout << a << endl;//a == 10cout << *p << endl;//*p == 20return 0;
}
对比监视列表和控制台,可以发现虽然在内存中a的值变为了20,但是打印时a仍为原来的10,这是因为编译器知道const修饰的变量不会被修改,那么编译器在编译阶段就会对其优化,即编译器会将常量的值直接内联到使用该常量的地方,而不是每次都访问内存中的存储位置,这一优化技术称为“常量折叠”或“常量传播”
补充:const修饰的局部变量仍然存放在栈上,修饰的全局变量才放在常量区中
volatile关键字
基本概念:用于指示编译器不对变量进行优化(带入上述代码再试一试即可)
volatile const int a = 10;//表示不会对a进行优化
结论:const_cast和reinterpret_cast都是强制类型转换(const_cast的第一个例子中的a去掉const修饰也能const_cast也能正常使用,且a打印时也为20),但是单独将const_cast拿出来就是因为可能出现因为编译器对const修饰的变量进行优化而导致的内存可见性
赋值兼容
基本概念:有继承关系的派生类与基类之间所遵循的赋值规则,包括向上和向下转型
- 向上转型:派生类对象赋值给基类对象(发生切片,切片 != 类型转换)、派生类的指针/引用赋值给基类的指针/引用(通常情况下都支持)(即这两种情况正常情况下都是可以支持的)
#include <iostream>
using namespace std;class A
{};class B : public A
{};int main()
{//向上转型B bb;A aa = bb;//派生类对象直接赋值给基类对象,发生切片A* ptr = &bb;//派生类对象的指针可以直接赋值给基类对象的指针B& cc = bb;A& str = cc;//派生类对象的引用可以直接赋值给基类对象的引用return 0;
}
- 向下转型:基类对象赋值给派生类对象(除非有相关的构造函数、否则即使是强转也转不了)、基类对象的指针/引用赋值给派生类对象的指针/引用(可以通过强转实现,但有越界风险需要得到控制)
//有相应的构造函数才能实现基类对象到派生类对象间的转换
#include <iostream>
using namespace std;class A {
public:int baseData;A() : baseData(0) {}A(int data) : baseData(data) {}
};class B : public A {
public:B() {};// 自定义构造函数,实现基类到派生类的转换B(const A& a) : A(a) {cout << "hello" << endl;}// 自定义赋值运算符,实现基类到派生类的转换B& operator=(const A& a) {cout << "world" << endl;return *this;}
};int main() {A aaa(10);B bbb;bbb = aaa; // 使用自定义赋值运算符B bbb2 = aaa; // 使用自定义构造函数return 0;
}
dynamic_cast
基本概念:为了能控制向下转型时的越界问题、C++提供了dynamic_cast类型转换操作符,dynamic_cast会在转换前检查是否能转换成功,可以转换就转换、不能转换就返回0
#include <iostream>
using namespace std;class A
{
public:virtual void f() {}int _a = 0;
};class B : public A
{
public:int _b = 1;
};void fun(A* pa)
{// 向下转换:父->子// pa指向子类对象,转回子类,是安全的// pa指向父类对象,转回子类,是不安全的,存在越界的风险问题// 不安全//B* pb = (B*)pa;// pa指向子类对象,转回子类,正常转换// pa指向父类对象,转回子类,转换失败B* pb = dynamic_cast<B*>(pa);if (pb){cout << pb << endl;cout << pb->_a << endl;cout << pb->_b << endl;}else{cout << "转换失败" << endl;}
}int main()
{A a;B b;fun(&a);//父类转为子类fun(&b);//子类转为子类return 0;
}
注意事项:dynamic_cast在使用时,基类要有虚函数(有就行)
~over~
相关文章:

C++中的类型转换操作符:static_cast reinterpret_cast const_cast dynamic_cast
目录 C语言中的类型转换 C中的类型转换 C中的类型转换操作符 static_cast reinterpret_cast const_cast volatile关键字 赋值兼容 dynamic_cast C语言中的类型转换 基本概念:赋值运算符左右两侧类型不同,或形参与实参类型不匹配…...
MySQL-SQL优化Explain命令以及参数详解
前言 在MySQL优化的众多手段中,EXPLAIN命令扮演着至关重要的角色。它是数据库管理员和开发者手中的利器,用于分析SQL查询的执行计划。通过执行EXPLAIN,MySQL会提供一份详细的查询执行计划报告,这份报告揭示了查询将如何执行&…...

别只会重启了!进来告诉你AP无法上线怎么办
号主:老杨丨11年资深网络工程师,更多网工提升干货,请关注公众号:网络工程师俱乐部 你们好,我的网工朋友。 作为网工,咱们都知道无线网络的重要性,尤其是对于企业网络来说,无线接入点…...

数据恢复篇:如何在 Android 手机上恢复未保存/删除的 Word 文档
在 Android 手机上访问 Word 文档通常很简单,但是当这些重要文件被删除或未保存时会发生什么?这种情况虽然令人痛苦,但并非毫无希望。到 2024 年,有几种强大的方法来处理此类数据丢失。本指南重点介绍如何在Android手机上恢复已删…...

Python | Leetcode Python题解之第208题实现Trie(前缀树)
题目: 题解: class Trie:def __init__(self):self.children [None] * 26self.isEnd Falsedef searchPrefix(self, prefix: str) -> "Trie":node selffor ch in prefix:ch ord(ch) - ord("a")if not node.children[ch]:retur…...

Ethernet是以太网通讯
...

咖啡消费旺季到来 为何想转让的库迪联营商却越来越多
文 | 智能相对论 作者 | 霖霖 去年还在朝“三年万店”计划狂奔的库迪,今年已出现明显“失速”。 早在今年2月,库迪就官宣其门店数已超过7000家,如今4个多月过去,据极海品牌监测数据显示,截至6月27日,其总…...

神经网络原理
神经网络原理是一种模拟人脑的机器学习技术,通过大量的神经元和层次化的连接进行信息处理和学习。 图1 神经元 神经网络由许多简单的计算单元或“神经元”组成,这些神经元通过连接传递信息。每个连接都有一个权重,用于调整传递的信号强度。这…...

安卓应用开发学习:获取经纬度及地理位置描述信息
前段时间,我在学习鸿蒙应用开发的过程中,在鸿蒙系统的手机上实现了获取经纬度及地理位置描述信息(鸿蒙应用开发学习:手机位置信息进阶,从经纬度数据获取地理位置描述信息)。反而学习时间更长的安卓应用开发…...

各类排序方法 手撕快排 回顾经典快排 优化版快排
快排的主要思想是分而治之 第一步,确定分界点,a 第二步,调整区间,利用分界点a,把小于分界点a的数放在左边,大于的放在右边,相等的放在哪都可以 第三步,递归处理左右两段 实现(暴…...

独一无二的设计模式——单例模式(Java实现)
1. 引言 亲爱的读者们,欢迎来到我们的设计模式专题,今天的讲解的设计模式,还是单例模式哦!上次讲解的单例模式是基于Python实现(独一无二的设计模式——单例模式(python实现))的&am…...
使用MoA(Mixture of Agents)混合智能体技术,结合多个开源大语言模型如Llama3、phi-3和Mistral,实现一个强大的AI智能体
1.简介 论文简介: 论文提出了一种称为混合智能体(Mixture-of-Agents,MoA)的方法,利用多个大语言模型(LLM)的集体智慧来提高自然语言理解和生成任务的性能。 MoA采用了分层结构,每一层包含多个LLM智能体。每个智能体都将前一层所有智能体的输出作为辅助信息来生成自己的回答。通…...
前端面试题_Css
一、说一下Css的盒子模型? HTML中所有元素都可以看成是一个盒子 盒子的组成:content、padding、border、margin 盒子的类型: 标准盒模型:marginborderpaddingcontent -- box-sizing:content-box(默认&a…...

AI在线免费视频工具3:声音生视频
1、声音生视频 Noisee:通过声音生成对应视频,可以增加prompt指定生成内容相关视频 https://noisee.ai/create...
final、const、readonly关键字在不同语言中代表着什么
一、Java 1.被final修饰的类不能被继承。 2.被final修饰的方法不能被重写。 被 final 修饰的类中所有的成员方法都会隐式的定义为 final 方法。 若父类中 final 方法的访问权限为 private ,则子类中不能直接继承该方法。此时可以在子类中定义相同方法名的函数&…...

HarmonyOS ArkUi Tabs+TabContent+List实现tab吸顶功能
Demo效果 Entry Component struct StickyNestedScroll {State message: string Hello WorldState arr: number[] []scroller new Scroller()StyleslistCard() {.backgroundColor(Color.White).height(72).width("100%").borderRadius(12)}build() {Scroll(this.sc…...

Hugging Face Accelerate 两个后端的故事:FSDP 与 DeepSpeed
社区中有两个流行的零冗余优化器 (Zero Redundancy Optimizer,ZeRO)算法实现,一个来自DeepSpeed,另一个来自PyTorch。Hugging FaceAccelerate对这两者都进行了集成并通过接口暴露出来,以供最终用户在训练/微调模型时自主选择其中之…...
TextField是用于在用户界面中输入文本的控件。它广泛应用于表单、搜索框、评论区等需要用户输入文字的场景
TextField是用于在用户界面中输入文本的控件。它广泛应用于表单、搜索框、评论区等需要用户输入文字的场景。以下是对TextField的详细解释,涵盖其各个方面的功能和属性。 基本属性 text 描述:TextField中当前显示的文本。用法:text: "示…...

MYSQL 四、mysql进阶 5(InnoDB数据存储结构)
一、数据库的存储结构:页 索引结构给我们提供了高效的索引方式,不过索引信息以及数据记录都是保存在文件上的,确切说时存储在页结构中,另一方面,索引是在存储引擎中实现的,Mysql服务器上的存储引擎负责对表…...

Spring企业开发核心框架-下
五、Spring AOP面向切面编程 1、场景设定和问题复现 ①准备AOP项目 项目名:Spring-aop-annotation ②声明接口 /*** - * / 运算的标准接口!*/ public interface Calculator { int add(int i, int j); int sub(int i, int j); int mul(int i, in…...

装饰模式(Decorator Pattern)重构java邮件发奖系统实战
前言 现在我们有个如下的需求,设计一个邮件发奖的小系统, 需求 1.数据验证 → 2. 敏感信息加密 → 3. 日志记录 → 4. 实际发送邮件 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其…...
椭圆曲线密码学(ECC)
一、ECC算法概述 椭圆曲线密码学(Elliptic Curve Cryptography)是基于椭圆曲线数学理论的公钥密码系统,由Neal Koblitz和Victor Miller在1985年独立提出。相比RSA,ECC在相同安全强度下密钥更短(256位ECC ≈ 3072位RSA…...

【OSG学习笔记】Day 18: 碰撞检测与物理交互
物理引擎(Physics Engine) 物理引擎 是一种通过计算机模拟物理规律(如力学、碰撞、重力、流体动力学等)的软件工具或库。 它的核心目标是在虚拟环境中逼真地模拟物体的运动和交互,广泛应用于 游戏开发、动画制作、虚…...

React第五十七节 Router中RouterProvider使用详解及注意事项
前言 在 React Router v6.4 中,RouterProvider 是一个核心组件,用于提供基于数据路由(data routers)的新型路由方案。 它替代了传统的 <BrowserRouter>,支持更强大的数据加载和操作功能(如 loader 和…...
Java 8 Stream API 入门到实践详解
一、告别 for 循环! 传统痛点: Java 8 之前,集合操作离不开冗长的 for 循环和匿名类。例如,过滤列表中的偶数: List<Integer> list Arrays.asList(1, 2, 3, 4, 5); List<Integer> evens new ArrayList…...
Admin.Net中的消息通信SignalR解释
定义集线器接口 IOnlineUserHub public interface IOnlineUserHub {/// 在线用户列表Task OnlineUserList(OnlineUserList context);/// 强制下线Task ForceOffline(object context);/// 发布站内消息Task PublicNotice(SysNotice context);/// 接收消息Task ReceiveMessage(…...
FastAPI 教程:从入门到实践
FastAPI 是一个现代、快速(高性能)的 Web 框架,用于构建 API,支持 Python 3.6。它基于标准 Python 类型提示,易于学习且功能强大。以下是一个完整的 FastAPI 入门教程,涵盖从环境搭建到创建并运行一个简单的…...

LeetCode - 394. 字符串解码
题目 394. 字符串解码 - 力扣(LeetCode) 思路 使用两个栈:一个存储重复次数,一个存储字符串 遍历输入字符串: 数字处理:遇到数字时,累积计算重复次数左括号处理:保存当前状态&a…...

ElasticSearch搜索引擎之倒排索引及其底层算法
文章目录 一、搜索引擎1、什么是搜索引擎?2、搜索引擎的分类3、常用的搜索引擎4、搜索引擎的特点二、倒排索引1、简介2、为什么倒排索引不用B+树1.创建时间长,文件大。2.其次,树深,IO次数可怕。3.索引可能会失效。4.精准度差。三. 倒排索引四、算法1、Term Index的算法2、 …...
三体问题详解
从物理学角度,三体问题之所以不稳定,是因为三个天体在万有引力作用下相互作用,形成一个非线性耦合系统。我们可以从牛顿经典力学出发,列出具体的运动方程,并说明为何这个系统本质上是混沌的,无法得到一般解…...