当前位置: 首页 > news >正文

C++性能优化笔记-6-C++元素的效率差异-7-类型转换

C++元素的效率差异

  • 类型转换
    • signed与unsigned转换
    • 整数大小转换
    • 浮点精度转换
    • 整数到浮点转换
    • 浮点到整数转换
    • 指针类型转换
    • 重新解释对象的类型
    • const_cast
    • static_cast
    • reinterpret_cast
    • dynamic_cast
    • 转换类对象

类型转换

在C++语法中,有几种方式进行类型转换:

// Example 7.19
int i; float f;
f = i; 						// Implicit type conversion
f = (float)i; 				// C-style type casting
f = float(i); 				// Constructor-style type casting
f = static_cast<float>(i); 	// C++ casting operator

这些不同的方法有完全相同的效果。使用哪种方法是一个编程风格的问题。下边讨论下不同转换的时间损耗。

signed与unsigned转换

。。。
有符号与无符号整数间的转换只是让编译器以不同的方式解释整数的比特。不检查溢出,代码不需要额外时间。

整数大小转换

int i; short int s;
i = s;

一个整数转换成一个位数更长的整数时,如果是有符号的,通过扩展符号位,如果是无符号的,通过零扩展。如果是一个算术表达式的结果进行,通常需要1时钟周期。如果从内存读取一个变量的值来转换,通常不需要额外时间,如下:
。。。
将整数转换到更小的类型仅仅是忽略高位比特,不检查溢出。例如:
。。。
这个转换不需要额外时间。它只是保存32位整数的低16位。

浮点精度转换

在使用浮点寄存器栈时,float、double与long double间的转换不需要额外时间。在使用XMM寄存器时,需要2到15时钟周期(取决于处理器)。例子:

// Example 7.24
float a; double b;
a += b;

在这个例子中,如果使用XMM寄存器,转换是相对低效的。a与b应该是相同类型以避免。

整数到浮点转换

有符号整数到float或double的转换需要4 ~ 6时钟周期,取决于处理器与使用的寄存器类型。无符号整数的转换需要更长时间,除非AVX512指令集可用(AVX512DQ用于64bit无符号整数)。如果没有溢出的危险,首先把无符号整数转换到有符号整数会更快的:
。。。

浮点到整数转换

浮点值到整数的转换需要非常长的时间,除非启用SSE2或更新的指令集。通常,转换需要50 ~ 100时钟周期。原因是C/C++标准指定截断,因此浮点取整模式必须改变为截断,再改回来。

如果在代码的关键部分存在浮点到整数转换,那么对进行优化是重要的。可能的方案有:

  • 使用不同类型的变量,避免转换。
  • 将中间结果保存为浮点类型,将转换移出最里层循环。
    。。。

指针类型转换

指针可以被转换到另一个类型的指针。类似的,指针可以转换到整数,或者整数可以转换到指针。整数有足够的bit位保存指针是重要的。
这些转换不会产生额外的代码。它只是以不同的方式解释相同比特,或者绕过语法检查。
当然,这些转换不安全。确保结果有效是程序员的责任。

重新解释对象的类型

通过转换地址类型,使编译器将一个变量或对象当做另一个类型是可能的:

float x;
*(int*)&x |= 0x80000000;	// Set sign bit of x

这里,语法看起来有些奇怪。x 的地址被类型转换为一个整数指针,然后通过把x当做整数访问。实际上制作一个指针,编译器不产生任何额外的代码真正创造一个指针。这个指针只是被优化掉,结果x被处理为一个整数。但 & 操作符强制编译器在内存而不是寄存器里保存x。上面例子通过使用只能应用于整数的 | 操作符设置 x 的符号位。它比x = -abs( x );更快。

在类型转换指针时,要小心一些风险:

  • 违反严格的标准C别名规则,尤其是不同类型的两个指针不能指向相同的对象(除了char指针)。优化编译器可能在两个不同的寄存器中保存浮点与整数表示。你需要检查编译器的行为是否就是你所期望的。使用联合更安全。
  • 如果对象被当做比其实际更大的类型对待,该技巧会无效。上面这个代码将出错,如果int比float使用更多比特。(在x86系统里,两者都使用32比特)。
    。。。

const_cast

const_cast用于去除一个指针的const限制。它有一些语法检查,因此,比C风格的类型转换更安全,无需添加任何额外的代码。例如:
。。。

static_cast

static_cast操作符做的与C形式的类型转换相同。

reinterpret_cast

reinterpret_cast操作符用于指针转换。与c风格的转换类似,但会进行一些语法检查,不产生任何额外的代码。

dynamic_cast

dynamic_cast操作符用于将一个类指针转换为另一个类的指针。它对转换的有效性进行运行时检查。例如,在一个基类指针被转换为派生类的指针时,它检查原始指针是否真的指向派生类的一个对象。这个检查使得dynamic_cast比简单的类型转换更耗时些,但也更安全。它可能捕捉到原本没发现的编程错误。

转换类对象

涉及类对象的转换(而不是对象指针)是看可能的,只要程序员定义了说明如何进行这个转换的一个构造函数、一个重载赋值操作符或一个重载类型转换操作符。构造函数或重载操作符与成员函数效率相同。

欢迎交流
在这里插入图片描述

http://www.lryc.cn/news/219725.html

相关文章:

  • c#中switch常用模式
  • Flink SQL 常用作业sql
  • nodejs国内镜像及切换版本工具nvm
  • 用Rust和Scraper库编写图像爬虫的建议
  • Java 语言环境搭建
  • 酷开科技 | 酷开系统里萌萌哒小维在等你!
  • Bash 4关联数组:错误“声明:-A:无效选项”
  • 干货|AI辅助完成论文的正确打开方式!
  • SpringBoot--Web开发篇:含enjoy模板引擎整合,SpringBoot整合springMVC;及上传文件至七牛云;restFul
  • 线上JAVA应用平稳运行一段时间后出现JVM崩溃问题 | 京东云技术团队
  • 进口跨境商城源码:高效、安全、可扩展的电商平台解决方案
  • GEE数据集——2019、2020、2021、2022和2023年全球固定宽带和移动(蜂窝)网络性能Shapefile 格式数据集
  • 什么是防火墙?详解三种常见的防火墙及各自的优缺点
  • 动态规划算法实现0-1背包问题Java语言实现
  • linux查看系统版本
  • pg14-sql基础(四)-多表联查
  • el-date-picker 日期时间选择器 限时时间范围 精确到时分秒
  • 轮廓线dp:GYM103446C
  • 羊驼免疫制备纳米抗体
  • 【AI好好玩02】利用Lama Cleaner本地实现AIGC试玩:擦除对象、替换对象、更换风格等等
  • SQL FULL OUTER JOIN 关键字(完整外部连接)||SQL自连接 Self JOIN
  • 专科医院污水处理设备构造解析及工艺流程
  • 【RabbitMQ】RabbitMQ 消息的可靠性 —— 生产者和消费者消息的确认,消息的持久化以及消费失败的重试机制
  • 百万套行泊一体量产定点,中国市场「开启」智驾高低速集成
  • Gopro hero5运动相机格式化后恢复案例
  • Microsoft Dynamics 365 CE 扩展定制 - 6. 增强代码
  • 基于libopenh264 codec的svc分层流实现方案
  • 为机器学习算法准备数据(Machine Learning 研习之八)
  • 基于Python OpenCV的金铲铲自动进游戏、D牌...
  • c++中httplib使用