《c++primer》ch2 变量和基本类型

数据类型决定了程序中数据和操作的意义。

2.1 基本内置类型

基本数据类型:** 算数类型 空类型(void) **,其中算数类型包括:字符、正整数、布尔值、浮点数。空类型不对应具体的值,用于一些特殊的场合。

2.1.1 算数类型

分为整形和浮点型。

整形:

  • bool:取值为true或者false。
  • char:基本的字符类型,一个char的大小与一个机器字节一样。
  • wchar_t,char16_t,char32_t
    ** rules: **一个int至少和一个short一样大,一个long至少跟一个int一样大,一个long long至少跟一个long一样大。

浮点型:

  • float:一般一个字,32bit
  • double:2个字,64bit
  • long double:3或4个字,96或128bit

带符号类型和无符号类型

2.1.2 类型转换

转换过程:

  • 非bool到bool:初始为0则为false,其他为true
  • bool到非bool:初始值为false则为0,初始值为true为1
  • 浮点数到整型:仅保留浮点数中的** 小数点部分 **
  • 整数到浮点数:小数部分记为0,如果整数所占的空间超过浮点类型的容量,会报错。
  • 赋给无符号类型,当超出它表示范围的时候,转换为该无符号类型表示数值总数取模后的余数。
  • 给带符号的数输出超过范围的值是,结果时** 未定义的 **

tips:一般不在算数表达式中使用bool值

含有无符号类型的表达式

一般不要混用无符号和有符号的类型,当无符号超过范围时,可能会出现取模的情况,放在循环中,或者计算结果中,会产生无法预计的结果

2.1.3 字面值常量

顾名思义,字面值常量一望而知。每个字面值常量对应一种数据类型,字面量常量得形式和值决定了它的数据类型。

整型和浮点型字面值

严格来说,十进制字面值不会是负数,通常,负号并不在字面值内,它的作用仅仅是对字面值取负值而已。

字符和字符串字面值

  • char型字面值:由单引号括起来的一个字符
  • 字符串字面值:由双引号括起来的零个或多个字符
    ** Note:字符串字面值的类型实际上是由常量字符组成的数组,编译器在每个字符串的结尾处添加一个空字符('\0'),字符串的字面值的实际长度比它的内容多1。 **

转义序列

有两类不能直接使用的字符。不可打印的和特殊含义的字符(单引号,双引号,问号,反斜线),这些情况下需要使用转义字符。

指定字面值类型

添加一定的前缀和后缀,可以改变整型、浮点型和字符型字面值的默认类型。前缀有:u(Unicode16)、U(Unicode32)、L(宽字符)、u8(UTF-8)。后缀有:u或者U(unsigned)、l或者L(ling)、ll或者LL(long long),f或者F(float)、l或者L(long double)。

布尔字面值和指针字面值

bool:true、false
指针:nullptr

2.2 变量

对于c++来说,一般“变量”和“对象”可以互换使用。对象时具有某种数据类型的内存空间。

2.2.1 变量定义

基本形式:类型说明符+一个或多个变量名组成的列表(变量名以逗号分隔)+分号

初始值

当对象在创建时获得了一个特定的值,称为被初始化了。** 初始化和复制是两个完全不同的操作,注意这个概念很重要 **
初始化:在创建变量是赋予其一个初始值。
复制:把对象的当前值擦除,以一个新的值代替。

列表初始化

无论是初始化对象还是某些时候为对象赋新值,都可以使用一组又花括号括起来的初始值。

int units_sold=0;
int units_sold={0};
int units_sold{0};
int units_sold(0);

默认初始化

定义于函数体内的内置类型的对象如果没有初始化,则其值未定义。类的对象如果没有显式的初始化,则其值由类确定。。建议初始化每一个内置类型的变量。

2.2.2 变量声明与定义的关系

声明使得名字为程序所知,定义负责创建与名字关联的实体。
** extern **关键字:如果想声明一个变量而不是定义它,就在变量名前添加extern,而不显示的初始化变量。如果在函数体内部试图初始化一个有extern关键字标记的变量,会引发错误。

2.2.3 标识符

用户自定义的标识符中不能出现两个连续的下划线,也不能以下划线紧连大写字母开头。定义在函数体内的标识符不能以下划线开头。

变量命名规范

  • 标识符要能体现实际含义
  • 变量名一般小写字母
  • 自定义的类名一般大写字母开头
  • 标识符由多个单词组成时,单词应有明显区分,使用下划线

2.2.4 名字的作用域

当内层出现与外层相同的名字时,使用内层定义的名字。

2.3 复合类型

复合类型指的是基于其他类型定义的类型。这里介绍两种:引用和指针。

2.3.1 引用

引用为对象起了另外一个名字,引用;类型引用另外一种类型。通过将生命符写成&d的形式来定义引用类型,其中d是声明的变量名。引用必须初始化。

引用即别名

引用并不是对象,只是一个已经存在的对象起的另外一个名字。定义了一个引用之后,对其做的所有操作都是在与之绑定的对象上进行的。
因为引用本身只是一个别名,不是一个对象,所以不能定义引用的引用。

引用的定义

除了两种例外的情况,其他所有的引用类型都要与之绑定的对象严格比配。
引用只能绑定到对象上,不能绑定到字面值或者某个表达式的计算结果上。

2.3.2 指针

指针是“指向point to”的另外一种类型的复合引用。指针也实现了对其他对象的间接访问。
两者的不同点:

  • 1.指针本身就是一个对象,允许对指针赋值和拷贝,而且指针的生命周期内可以指向多个不同的对象。
  • 2.指针无需在定义时赋初值。

获取对象的地址

指针存放某个对象的地址,要想获取该地址,需要使用取地址符(操作符&)
不能定义指向引用的指针(因为引用不是一个对象)。
除了两种例外的情况,所有指针的类型都要和它指向的对象严格匹配。

指针值

指针的值(即地址)应该属于下面四种状态之一:

  • 1.指向一个对象
  • 2.指向紧邻对象所占空间的下一个位置
  • 3.空指针,表示没有指向任何对象。
  • 4.无效指针,上述之外的其他值。

利用指针访问对象

如果指针指向了一个对象,允许使用解引用符(操作符*)来访问对象。

空指针

空指针不指向任何对象,得到空指针的办法:直接用字面值nullptr初始化指针或者将指针初始化为字面值0来生成空指针。
** 建议 **:初始化所有指针

赋值和指针

记住赋值永远改变的是等号左侧的对象。

其他指针操作

只要一个指针拥有合法值,就能将它用在条件表达式中,只要不为空,条件都为true。

void* 指针

void* 是一种特殊的指针类型,可用于存放任意对象的地址。

2.3.3 理解复合类型的声明

变量的定义包括:一个基本数据类型+一组声明符。基本数据类型只有一个,但是声明符的形式可以不同。

指向指针的指针

当有多个修饰符连写在一起的时候,按照逻辑关系解释。

指向指针的引用

引用本身不是对象,但是指针是对象,所以可以对指针引用。
面对一条复杂的指针或引用的声明语句时,从右向左阅读有助于弄清真实含义。

2.4 const限定符

初始化和const

const与非const对象的区别就是,const类型的对象执行不改变起内容的操作。如:const int也能像int一样参与算术运算,也能转化为bool值。

默认状态下,const对象仅在文件内有效

如果想在多个文件之间共享const对象,必须在变量定义之前添加extern关键字。

2.4.1 const的引用

可以把引用绑定到const对象上,就像绑定到其他对象上一样,称为对常量引用,对常量的引用不能修改它所绑定的对象。
** 术语:常量引用是对const的引用 **:并不存在常量引用,是对const的引用。

初始化和对const的引用

引用情况的例外:第一种是,在初始化常量引用时,允许用任意表达式作为初始值,只要该表达式的结果能转换成引用的类型即可。尤其允许为一个常量引用绑定非常量的对象、字面值,甚至是个一般表达式。

对const的引用可能引用一个非const的对象

此种行为是合法的,但是不能通过对const的引用改变对象的值,兑现可以通过其他的方式改变值。

2.4.2 指针和const

指向常量的指针不能改变其所指对象的值,要想存放常量对象的地址,只能只用指向常量的指针。
所谓指向常量的指针和引用,只是自以为指向了一个常量,所以自觉不去改变所指对象的值。

const指针

*const:不变的是指针的值而不是指向的那个值。采用从右向左的方式阅读,看离最近的符号。

顶层const

顶层const表示指针本身是个常量,底层const表示指针指的对象是一个常量。
当对象执行拷贝操作时,顶层const不受影响,拷入和拷出的对象必须具有相同的底层const资格,或者两个对象的数据类型必须能够转化。

2.4.4 constexpr和常量表达式

常量表达式指:值不会改变且在编译过程就能得到计算结果的表达式。(字面值、用常量表达式初始化的const对象)

constexpr变量

声明为constexpr的变量一定是一个变量,且必须用常量表达式初始化。

字面值类型

指针和constexpr

在constexpr如果定义了一个指针,则constexpr只对指针有效,与指针所指的对象无关。

2.5 处理类型

2.5.1 类型别名

类型别名是一个名字,是某种类型的同义词。使用方式:

typedef double wages  //wages 是double的别名
typedef wages base,*p

#别名声明
using SI=Scales_item;

指针、常量和类型别名

2.5.2 auto类型说明符

复合类型、常量和auto

  • 引用时的auto,以引用对象的类型作为auto的类型
  • auto一般会忽略掉顶层const,底层const会保留下来。
  • 可以将引用的类型设为auto

2.5.3 decltype类型指示符

选择并返回操作数的类型,编译器分析表达式并得到类型,但并不实际计算值

decltype和引用

有些表达式将向decltype返回一个引用类型。如果表达式的内容是解引用操作,则decltype将得到引用类型。
解引用指针可以得到指针所指的对象,而且还能给这个对象赋值。
decltype和auto的重要区别:decltype的结果类型与表达式形式密切相关。
** 如果给变量加上一层或多层括号,decltype就会得到引用类型。decltype((val))的结果永远是引用,decltype(val)只有当val本身是一个引用时才是引用。另外,赋值是会产生引用的一类典型表达式,引用的类型就是左值的类型 **

2.6 自定义数据结构

定义自己的数据结构

定义自己的头文件

预处理器

你可能感兴趣的:(《c++primer》ch2 变量和基本类型)