C++使用列表初始化避免缩窄转换错误

news/2025/2/2 10:50:47/

C++使用列表初始化避免缩窄转换错误

1. 防止类型收窄

(1)类型收窄:指的是导致数据内容发生变化或者精度丢失隐式类型转换

(2)类型收窄的几种情况:

①从浮点数隐式转换为整型数,如 int i = 2.2;

②从高精度浮点数隐式转换为低精度浮点数。如从 long double 转 double 或 float。

③从整型数隐式转换为浮点数,并且超出浮点数的表示范围,如 floa t= (unsigned long long) - 1,注意这表示将 -1先强制转换为unsigned long long,再隐式转换为 float。

④从整型数隐式转换为长度较短的整型数,并且超出其表示范围。如 char x = 65536。

(3)在C++98/03中,类型收窄编译器不会报错,而C++11中可以通过列表初始化来检查及防止类型收窄

2. explicit关键字

(1)explicit用于阻止编译器的隐式转换,一般用于修饰构造函数

(2)C++98/03由于不能使用{}列表初始化,即隐式转换只发生在调用带一个参数的构造函数中。但C++11允许用{}列表初始化对象,这可能会隐式调用带多个参数的构造函数

(3)C++11中,explicit可用于修饰带多个参数的构造函数以防止隐式转换。(注意C++98/03中explicit被用于修饰只带一个参数的构造函数,如果修饰带多个参数的构造函数则无效)

使用取值范围较大的变量来初始化取值范围较小的变量时,将面临出现缩窄转换错误的风险,因为编译器必须将大得多的值存储到容量没那么大的变量中,下面是一个这样的示例:

int largeNum = 5000000;
short smallNum = largeNum; // compiles OK, yet narrowing error

缩窄转换并非只能在整型之间进行,但如果使用 double 值来初始化 float 变量、使用 int 值来初始化 float 或 double 变量,或者使用 float 值来初始化 int 变量,可能导致缩窄转换错误。有些编译器可能发出警告,但这种警告并不会导致程序无法通过编译。在这种情况下,程序可能在运行阶段出现 bug,但这种 bug 并非每次运行时都会出现。
为避免这种问题, C++11 引入了列表初始化来禁止缩窄。要使用这种功能,可将用于初始化的变量或值放在大括号( {})内。列表初始化的语法如下:

int largeNum = 5000000;
short anotherNum{ largeNum }; // error! Amend types
int anotherNum{ largeNum }; // OK!
float someFloat{ largeNum }; // error! An int may be narrowed
float someFloat{ 5000000 }; // OK! 5000000 can be accomodated

这种功能的作用虽然不明显,但可避免在执行阶段对数据进行缩窄转换导致的 bug:这种 bug 是不合理的初始化导致的,难以发现。

该文章会更新,欢迎大家批评指正。

推荐一个零声学院免费公开课程,个人觉得老师讲得不错,
分享给大家:Linux,Nginx,ZeroMQ,MySQL,Redis,
fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,
TCP/IP,协程,DPDK等技术内容,点击立即学习:
服务器课程:C++服务器


http://www.ppmy.cn/news/1008722.html

相关文章

微信小程序的自定义TabBar及Vant的使用

一、安装Vant 1、在 资源管理器 空白位置,点右键打开 在外部终端窗口打开 2、初始化NPM npm init -y 3、安装命令 npm i vant/weapp1.3.3 -S --production 4、构建NPM包 在 工具 里选择构建NPM包 5、删除style:v2 在app.json里,删除"style"…

Cookie vs Session:Web开发中的身份验证之争

Cookie vs Session:Web开发中的身份验证之争 前言一、概述二、Cookie和Session的区别与联系三、登陆案例讲解1、以登录案例讲解Cookie的使用过程2、以登陆案例讲解 Session 的使用过程 四、总结 前言 本博主将用CSDN记录软件开发求学之路上亲身所得与所学的心得与知…

58Set 和 Map 数据结构

Set 和 Map 数据结构 SetWeakSetMapWeakMapWeakRefFinalizationRegistry Set 基本用法 ES6 提供了新的数据结构 Set。它类似于数组,但是成员的值都是唯一的,没有重复的值。 Set本身是一个构造函数,用来生成 Set 数据结构。 const s ne…

Dockerfile定制Tomcat镜像

Dockerfile中的打包命令 FROM : 以某个基础镜像作为此镜像的基础 RUN : RUN后面跟着linux常用命令,如RUN echo xxx >> xxx,注意,RUN 不能用于执行命令,因为每个RUN都是独立运行的,RUN 的cd对镜像中的…

TensorFlow搭建神经网络

TensorFlow版本:2.13.0TensorFlow官方文档TensorFlow官方文档中文版 TensorFlow中搭建并训练一个神经网络分为以下几步: 定义神经网络配置损失函数以及优化器训练:反向传播、梯度下降 下面以LeNet-5为例,搭建一个卷积神经网络用…

【Spring】使用注解存储Bean对象

目录 一、配置扫描路径(使用注解的方式存对象的前提) 二、使用类注解存储Bean对象 1、使用五大类注解存储Bean对象 2、为什么要这么多的类注解? 2.1、五大类注解之间的关系 3、获取Bean对象时的默认命名规则 三、使用方法注解来存储…

利用线程池多线程并发实现TCP两端通信交互,并将服务端设为守护进程

文章目录 实现目标实现步骤封装日志类封装线程池封装线程封装锁封装线程池 TCP通信的接口和注意事项accept TCP封装任务客户端Client.hppClient.cc 服务端Server.hpp Server.cc实现效果 守护进程服务端守护进程化 实现目标 利用线程池多线程并发实现基于TCP通信的多个客户端与…

CVE漏洞复现-CVE-2019-5021 镜像漏洞利用

CVE-2019-5021 镜像漏洞利用 随着容器技术的普及,容器镜像也成为软件供应链中非常重要的一个组成的部分。人们像使用 pip 等工具从仓库获取各种编程软件库一样,可以从 Docker Hub 或 第三方仓库拉取镜像,在其基础上进行开发,从而…