C++类型与声明

发布于:2024-05-09 ⋅ 阅读:(30) ⋅ 点赞:(0)

类型与声明

类型

字符类型

  • char 默认类型,通常占8位, 是否带符号以来于实现。
  • signed char 可以存放正值也可以存放负值
  • unsigned char 不带符号
  • wchar_t 用于存放unicode 等更大的字符集。wchar_t 的尺寸依赖实现
  • char16_t 用于存放UTF-16的16位字符集
  • char32_t 用于存放UTF-32的32位字符集

对于char, signed char, unsigned char, 这三个名字代表的类型各不相同。我们不能混用这三个类型的指针。
编译会报类似下面的错误: invalid conversion from ‘char*’ to ‘unsigned char*’ [-fpermissive]

  • 单引号的char 字符: 把多个字符放在一对单引号内,比如’ab’这个结果完全依赖实现,尽量避免使用
  • 双引号的char 字符:
    • char v1[] = “a\xah\129”; 6个字符‘a’ ‘\xa’ ‘h’ \12’ ‘9’ ‘\0’
    • char v2[] = “a\xah\127”; 5个字符‘a’ ‘\xa’ ‘h’ \127’ ‘\0’
    • char v3[] = “a\xad\127”; 4个字符‘a’ ‘\xad’ \127’ ‘\0’
    • char v4[] = “a\xad\0127”; 5个字符‘a’ ‘\xad’ \012’ ‘\7’ ‘\0’

整数类型

  • 如果需要精细的控制整数的尺寸,可以使用 中定义的别名, 包括int64_t 等
  • 后缀U 显示的指定unsigned 字面值常量
  • 后缀L 显示的指定long 字面值常量

声明

  • 声明的结构, 包含5个部分
    • 可选的前置修饰符(比如static 和 virtual)

      • 修饰符指的是声明语句中最开始的关键字,如virtual,extern, constexptr 等,作用是指定所声明对象的某些非类型属性
    • 基本类型(比如 vector 和 const int)

    • 可选的声明符,可包含一个名字(比如p[7], n 和 ()[]) 由一个名字和一些可选的声明运算符组成

      声明运算符
      前缀 * 指针
      前缀 *const 常量指针
      前缀 *volatile volatile 指针
      前缀 & 左值引用
      前缀 && 右值引用
      前缀 auto 函数(使用后置返回类型
      后缀 [] 数组
      后缀 () 函数
      后缀 -> 从函数返回

      后缀声明符的绑定效果比前缀的声明符更加紧密, 所以char* kings[] 是char 指针的数组, 而char (*kings)[] 是 指向char 数组的指针。
      如果需要声明“数组的指针” 或者 “函数的指针”, 则必须使用括号加以限定。

    • 可选的后缀函数修饰符(比如const 和 noexcept)

    • 可选的初始化器或函数体(比如 = {7,5,3})

声明,看似简单,但是掺杂了前缀和后缀后变得很难理解

声明多个名字

  • 允许在同一条语句中声明多个名字,其中包含逗号隔开的多个声明符
int x,y;
  • 但是需要注意在声明语句中,运算符只作用于紧邻的一个名字,对于后续的其它名字是无效的。
int* p,y; 声明的是int* p; int y
int v[10], *pv; 声明的是int v[10], int *pv;
  • 良好的编码习惯尤为重要,一个良好的编码不会出现上面的情况。

名字

  • 起名字犹如艺术家的创作,看似简单,实则每个都要深思熟虑才行
  • 对于以前的C 编码规范,习惯于把类型缩写放在变量明称前面,或者加上g+ …, str…, 这个方式不提倡

初始化

初始化器有四种可能的形式:

(1)X a1 {v};
(2)X a2 = {v};
(3) X a3 = v;
(4) X a4(v);
  • (1) 列表初始化 : 形式不受任何限制,提倡使用的方法 能够防止窄化转换
    • 窄化转化 的概念
      • 如果一个整型存不下另一个整型, 则后者不会被转化为前者。例如允许char 到int 的转化,但是不允许int 到char 的转化
      • 如果一个浮点型装不下另一个浮点型的值, 则后者不会被转化为前者。允许float 到double 的转化,但是不允许double 到float 的转化
      • 浮点型不能转化为整形
      • 整型值不能转化为浮点型
    • 使用auto 关键字从初始化器推断变量类型时,不能使用列表初始化器,初始化的类型是initializer_list 类型。所以auto 不建议采用初始化列表

对象和值

左值和右值

  • 理解左值和右值, 从概念上很难理解,但是从以下两个属性方面理解,会容易理解些:
    有身份 在程序中有对象的名字, 或指向该对象的指针,或该对象的引用。
    可移动 能把对象的内容移动出来(比如我们能把它的值移动到其他出来,剩下的对象处于合法,但是未指定的状态)

    使用m 表示可以移动, i 表示有身份,可以有以下三种组合:

    • 左值(i&!m)
    • 特别值(i & m)
    • 纯右值(!i & m)
      泛左值 包括左值和特别值
      右值 包括 特别值和纯右值
  • std::move(vs) 是一个特别值(不确定是否还有其他特别值)

  • 在实际代码编写中,考虑左值和右值就足够了,一条表达式要么是左值,要么是右值。