首页 > 其他分享 >learncpp-10 类型转换、类型别名、类型推导

learncpp-10 类型转换、类型别名、类型推导

时间:2024-07-22 22:33:35浏览次数:12  
标签:类型转换 10 转换 初始化 constexpr 类型 learncpp 窄化

10 类型转换、类型别名、类型推导

10.4 窄化转换(收缩转换)、列表初始化和constexpr初始化器

  • 窄化转换是一种不安全的数值转换:目标类型可能无法保存源类型的所有值
  • 以下转换是窄化的:
    • 浮点型转换成整型
    • 从浮点型转换成等级更低的浮点型(除非被转换的值是constexpr并且在目标类型的范围内)
    • 从整型转换成浮点型(除非要转换的值是constexpr并且值可以精确地存储在目标类型中)
    • 从一个整型转换成另一个不能表示源类型的所有值的整型(除非要转换的值是constexpr并且其值可以精确地存储在目标类型中)(包括两种情况:宽整型到窄整型的转换、有符号整数转换成到无符号整数或者反过来)
  • 避免使用窄化转换
  • 使用static_cast来显式执行窄化转换可以避免编译器的警告
  • 使用大括号初始化时不允许窄化转换(这也是大括号初始化的主要优点之一),否则会产生编译错误
  • 如果窄化转换的源值是constexpr,那么编译器已经知道了要被转换的值,也就知道了这个值是否会在转换后被保留(如果会被保留则认为这不是窄化转换,如果不会被保留则编译报错)
const int i{128};
char c{i}; // 如果i的值在-128到127之间,则编译通过;否则编译报错:Constant expression evaluates to 128 which cannot be narrowed to type 'char'
// 注意!!!这里编译报错是因为大括号初始化不允许窄化转换;如果使用的是=初始化c,则编译器只会警告出现了窄化转换,而不会报错
  • 从constexpr浮点型转换成更窄的浮点型不是窄化转换,即使损失了精度
constexpr double d{0.1};
float f {d};// compile ok
  • 当使用列表初始化来初始化非int/非double的对象时,选择constexpr表达式作为初始化器可以避免窄化转换

10.6 显式类型转换和static_cast

  • C++提供了5种类型转换:C风格转换、静态转换、常量转换、动态转换、重新解释转换,后四种类型也称为命名转换

尽量避免使用常量转换和重新解释转换

  • C风格转换的形式是(type_name)variable_name或者type_name(variable_name)

尽管C风格转换看起来是单一的转换,但实际上它可以根据上下文执行各种不同的转换,包括静态转换、常量转换和重新解释转换
因此,尽量避免使用C风格转换

  • static_cast是一个运算符,它接收一个表达式作为输入,然后计算得到一个指定类型的值。最适合用于将一种基本类型转换为另一种基本类型

static_cast的主要优点是提供了编译时的类型检查

  • 使用static_cast可以显式进行窄化转换
  • 隐式类型转换和显式类型转换的区别

每当需要一种数据类型而提供了另一种数据类型时,都会自动执行隐式类型转换
而显式类型转换是程序员显式地使用类型转换运算符将一种类型转换成另一种类型

10.8 使用auto进行对象的类型推导

  • 类型推导是一个特性:允许编译器根据对象的初始化器来推断对象的类型
  • 字面量后缀可以和auto结合使用
auto a{1.2f}; // 变量a被推断为float类型
auto b{5u}; // 变量b被推断为unsigned int类型
  • 如果对象没有初始化器或者初始化器为空/void,则类型推断无效,以下三条语句都会编译报错
auto x;
auto y{};
auto z{f()}; // f()的返回类型为void
  • 类型推断会丢弃const/constexpr限定符,除非手动添加const/constexpr
const int x{5}; // x的类型是const int
auto y{x}; // y的类型是int
const auto z{x}; //z的类型是const int
  • 字符串字面量的类型推断结果为const char*,而不是std::string/std::string_view,除非在字符串字面量后面加上后缀s/sv
  • 类型推断的优点
    • 使用类型推断时,变量必须有初始化器,因此可以避免忘记初始化变量
    • 避免出现影响性能的转换
  • 类型推断的缺点
    • 类型推断使得变量的类型信息不那么直观
    • 使用类型推断时,当变量的初始化器的类型改变后,变量的类型也会改变
  • 当对象的类型不重要时,对变量使用类型推断

标签:类型转换,10,转换,初始化,constexpr,类型,learncpp,窄化
From: https://www.cnblogs.com/akongogogo/p/18317115

相关文章

  • learncpp-7 作用域、生存期、链接
    7作用域、生存期、链接用户自定义命名空间和范围解析运算符为了避免命名冲突,在尽可能小的作用域内定义标识符一个命名空间要么在全局作用域内定义,要么在另一个命名空间内定义使用范围解析运算符::可以告诉编译器去指定命名空间查找指定标识符(如果::前没有命名空间则表示全......
  • learncpp-14 类
    14类14.9构造器当类有私有成员时,无法使用聚合初始化构造器是一个特殊的成员函数,它在非聚合类的对象创建后自动调用构造器不会创建对象:编译器在调用构造器之前就为对象分配了内存,然后在未初始化的对象上调用构造函数构造器需要初始化对象的成员,因此不能为constconst对象不......
  • learncpp-12 复合类型:引用和指针
    12复合类型:引用和指针12.1复合数据类型介绍函数也是一种复合数据类型12.2左值和右值表达式除了可以产生值和副作用,还可以计算为对象或函数C++中的所有表达式都有两个属性:类型和值类别表达式的类型就是计算表达式得出的值、对象、函数的类型表达式的类型必须在编译时......
  • learncpp-20 函数
    20函数20.1函数指针函数和变量一样,也是在内存中被分配了一块地址。因此,函数指针就是一个保存函数的内存地址的变量函数也是有类型的,例如foo()这个函数的类型就是返回整数且不带参数intfoo(){return5;}<<操作符不知道如何输出函数指针(因为有无数种可能的函数指针),因......
  • learncpp-21 操作符重载
    21操作符重载21.12重载赋值运算符拷贝构造器和拷贝赋值运算符的作用几乎相同,都是将一个对象复制到另一个对象。但是拷贝构造器初始化新的对象,而赋值运算符替换已有对象的内容如果在拷贝前必须创建一个新对象,则使用拷贝构造器(包括按值传递和按值返回)如果在拷贝前无需创......
  • learncpp-1 C++基础
    1C++基础1.1语句和程序结构语句是一条让计算机执行某个动作的指令,是C++语言中最小的独立计算单元在高级语言(例如C++)中,一条语句可能编译成多条机器指令大多数语句以;结尾声明语句跳转表达式语句复合语句选择语句(条件语句)迭代语句(循环语句)try代码块函......
  • 2024杭电钉耙2-1003 HDOJ7447 绝对不模拟的简单魔方
    欢迎您来我的网站看这篇题解!Problem有一个魔方可能被拧了不超过三次,同时还弄丢了一个角块上的两个贴纸。现在把这两个贴纸贴回去,请问有没有贴错?只可能拧侧面,不会拧中间层,且每次只能拧\(90^\circ\)。魔方用一个9行12列的字符型矩阵表示:初始魔方的展开图如下图:\(1\leT......
  • learncpp-2 函数和文件
    2函数和文件2.9命名冲突和命名空间两个(或多个)同名函数(或全局变量)被引入到属于同一程序的不同文件中,这将导致链接器错误。两个(或多个)同名函数(或全局变量)被引入到同一个文件中。这将导致编译器错误。不同的作用域(例如命名空间)中可以有相同的标识符只有声明和定义可以出现......
  • Luogu P4310 绝世好题 题解 [ 绿 ] [ 线性 dp ] [ 单调队列优化 ] [ 二进制优化 ]
    题目:绝世好题。暴力dp显然\(O(n^2)\)转移即可。单调队列优化观察到只有某二进制位两个数都为\(1\)时才能转移,因此我们把每个二进制位开一个单调队列,然后对于一个数\(a\),找到它是\(1\)的二进制位并选其单调队列的队头进行转移,在这之后把这个数加入符合要求的单调队列......
  • 2024 Selenium10个替代品
     随着自动化测试需求的不断增长,Selenium作为广泛使用的自动化测试工具,虽然功能强大,但也存在一些限制和挑战。在2024年,越来越多的替代工具涌现,它们提供了更高效、更易用的解决方案。那么,哪些替代品值得我们关注呢?  在自动化测试领域,除了Selenium,还有哪些工具能够满足我们的......