变量与基本类型
int,long,long long的size区别
- 32位 int = long = 4byte,long long = 8byte
- 64位 int = 4 byte,long = long long = 8 byte
初始化与赋值的区别
- 在C++中,变量的初始化不是赋值,初始化的含义是创建变量时赋予其一个初始值,而赋值的含义是把对象的当前值擦除,而以一个新值来替代
变量初始化
- 如果定义变量时没有指定初始值,则变量被
默认初始化
,此时变量被赋予了默认值,默认值到底是什么由变量类型决定
- 同时定义变量的位置也会对此有影响,如果定义在任何函数体外,则其值会被
默认初始化为0
,但如果定义在函数体中,则该变量不会被初始化
,此时他的值是未定义的,对其进行拷贝或访问会引发错误
- 定义于函数体内的内置类型的对象如果没有初始化,则其值未定义,类的对象如果没有显式的初始化,则其值由类确定
- 初始化每一个内置类型的变量
变量的声明和定义
- 变量可以声明多次,但只能定义一次
- 如果想声明一个变量而非定义它,就在变量名前添加关键字
extern
,而且不要显式的初始化变量
- 任何包含了显式初始化的声明即成为定义
- 函数体内部不能初始化
extern
关键字标记的变量
静态类型
- C++是一种
静态类型
语言,其含义是在编译阶段检查类型,检查类型的过程称为类型检查
- 对象的类型决定了对象所能参与的运算,在C++中,编译器负责检查数据类型是否支持要执行的运算,如果试图执行类型不支持的运算,编译器将报错且不会生成可执行文件,由此,编译器必须知道每个实体对象的类型,这就要求必须在使用变量前声明其类型
标识符
- C++的标识符(变量名)由字母,数字,下划线组成,其中必须以字母或下划线开头,大小写敏感,无长度限制
- 命名规范
- [x] 体现实际含义
- [x] 变量名一般用小写
- [x] 用户自定义的类名一般以大写开头
- [x] 如果标识符由多个单词组成,应有明显区分,可以以下划线区分
引用
- 引用必须初始化
- 引用并非对象,相反,它只是为一个已经存在的对象所起的另外一个名字
- 引用初始化时会与变量绑定在一起
- 定义了一个引用之后,对引用的所有操作都是在与之绑定的对象上进行的
- 由于C++并不允许随意改变引用的绑定对象,所以所有引用都算是常量,引用的对象是常量还是非常量可以决定其所能参与的操作,却无论如何都不会影响到引用和对象的绑定关系
- 常量引用(即用const修饰的引用)可以在初始化时绑定任意表达式,只要表达式的结果能转换成基本类型,由此,允许为一个常量引用绑定非常量的对象/字面值/甚至表达式,如下述:
- [x] int i = 42;
- [x] const int &r1 = i
- [x] const int &r2 = 42
- [x] const int &r3 = r1 * 2
- [x] 此情况仅限于常量引用适用
- 常量引用仅对引用可参与的操作做出了限定,对于引用的对象本身是不是一个常量未作限定
指针
- 指针本身就是一个对象,允许对指针进行赋值和拷贝,而且在指针的生命周期内它可以先后指向几个不同的对象
- 指针无需在定义时赋初值
- 在块作用域内定义的指针如果没有被初始化,也将拥有一个不确定的值
- 指针的值应属于以下4种状态之一:
- [x] 指向一个对象
- [x] 指向紧邻对象所占空间的下一个位置
- [x] 空指针,不指向任何对象
- [x] 无效指针,上述情况之外的其他值
-
void *
是一种特殊的指针类型,可以存放任意对象的地址
- [x] `void *`指针只能用来与别的指针比较,作为函数的输入输出,或者赋值给另外一个`void *`指针,不能直接操作`void *`指针指向的对象,因为不知道该对象的类型
-
* &
是类型修饰符,他们本身不是类型,只作用与一次定义的临近变量
- [x] `int * p1,p2`,在这段声明中,`p1`是int的指针,`p2`是int
- 与引用一样,指针也可以指向常量或者非常量,
指向常量的指针
不能用于改变其所指对象的值,要想存放常量对象的地址,必须使用常量指针
- 总结:要想取一个常量的指针或者绑定一个常量引用,必须使用常量指针或常量引用,但常量指针与常量引用并不是只能作用于常量,常量引用可以在初始化时绑定变量甚至字面值,常量指针可以存储变量的地址,但不能通过常量指针或引用修改变量的值
const关键字
-
const
关键字的作用是限定变量的值不被改变,因为const
对象一旦创建后其值不能再改变,所以const
对象必须初始化
- [x] 默认状态下`const`对象仅在文件內有效
- [x] 当多个文件中出现了同名的`const`对象时,其实等于在不同文件中分别定义了独立的变量
- [x] 可以通过`extern`关键字使得`const`对象可以全局访问,
- [x] 如果想在多个文件之间共享`const`对象,必须在变量的定义之前添加`extern`关键字
- [x] 上述使用方式并不常见,有类似的需要可以通过宏完成
顶层const
- [x] int i = 0
- [x] int * const p = &1
- [x] 指针本身是常量(即是常量指针)
- [x] const int i = 10
- [x] const int * p = &1
- [x] 指针本身是变量,指针指向常量(即是常量的指针)
constexpr(常量表达式/const expression)
- C++11标准规定,允许将变量声明为
constexpr
类型以便由编译器来验证变量的值是否是一个常量表达式,声明为constexpr
的变量一定是一个常量,而且必须用常量表达式初始化
- 一般来说,如果认定变量是一个常量表达式,那就把它声明成
constexpr
类型
-
constexpr
所修饰的变量一定是编译期可求值的
-
constexpr
的好处
- [x] 是一种很强的约束,更好的保证程序的正确语义不被破坏
- [x] 编译器可以在编译期对`constexpr`的代码进行非常大的优化,比如将用到`constexpr`的都直接替换为最终结果
- [x] 相比宏来说,没有额外的开销,但更加可靠安全
-
constexpr
在声明中修饰指针的话,限定符仅对指针有效,与指针所指的对象无关(类似顶层const)
类型别名
- [x] 关键字typedef作为声明语句中的基本数据类型的一部分出现,含有typedef的声明语句定义的不再是变量而是类型别名
- [x] typedef double wages
- [x] typedef wages base,*p
- [x] using SI = Sales_item
- [x] 使用关键字using作为别名声明的开始,其后紧跟别名,其作用是把等会左侧的名字规定成等号右侧类型的别名
- 类型别名和类型的名字等价,只要是类型的名字能出现的地方,就能使用类型别名
auto类型说明符
- C++11引入
auto
类型说明符,用它就能让编译器替我们去分析表达式所属的类型,auto
通过初始值来推算变量的类型,所以auto定义的变量必须有初始值
- 要在一条语句中声明多个变量,切记,符号
&
以及*
只从属于某个声明符,而非基本数据类型的一部分,因此初始值必须是同一种类型
- 编译器推断出的
auto
类型有时候和初始值的类型并不完全一样,编译器会适当的改变结果类型使其更符合初始化规则,特别是当引用被用作初始值时
decltype类型指示符
- 当希望表达式的类型推断出要定义的变量的类型,但是不想用该表达式的值初始化变量,可以使用
decltype
-
decltype
的作用是选择并返回操作数的数据类型,在此过程中,编译器分析表达式并得到它的类型,却并不实际计算表达式的值:
- [x] decltype(f()) sum = x; //sunm的类型就是函数f的返回类型
- 编译器并不实际调用函数f,而是使用当调用发生时f的返回值类型作为sum的类型
- 如果
decltype
使用的表达式是一个变量,则decltype
返回该变量的类型(包括顶层const和引用在内)
-
decltype((variable))(注意是双括号)
的结果永远是引用,而decltype(variable)
结果只有当variable本身就是一个引用时才是引用
自定义数据结构
- 数据结构是把一组相关数据元素组织起来然后使用他们的策略和方法
- 结构体(
struct
)以及(class
)的定义最后要在花括号后面加上分号
- 为了保持各个文件中类的定义一致,类通常被定义在头文件中,而且类所在头文件的名字应该与类的名字一样
- C++11新标准规定,可以为数据成员提供一个
类内初始值
,创建对象时,类内初始值将用于初始化数据成员
预处理器
- 头文件一旦改变,相关的源文件必须重新编译以获取更新过的声明
- 确保头文件被多次包含仍能安全工作的常用技术是
预处理器
- 预处理器是在编译之前执行的一段程序,可以部分地改变我们所写的程序
- 当预处理器看到
#include
标记时就会用指定头文件的内容代替#include
- 预处理变量无视C++语言中关于作用域的规则
头文件保护符
- 头文件保护符依赖于预处理变量,预处理变量有两种状态,已定义和未定义.
-
#define
指令把一个名字设定为预处理变量,另外两个指令分别检查某个指定的预处理变量是否已经定义:#ifdefd
当且仅当变量已定义时为真,#ifndef
当且仅当变量未定义时为真,一旦检查结果为真,则执行后续操作直至遇到#endif
指令为止
#ifdef SALES_DATA_H
#define SALES_DATA_H
#include
struct{
......
......
};
# endif
- 头文件即使没有被包含在任何其他头文件中,也应该设置保护符,头文件保护符应该 每个头文件都写
小结
- 类型是C++语言的基础
- 类型规定了其对象的存储要求和所能执行的操作
- C++语言提供了一套基础内置类型,如int和char等,这些类型与实现它们的机器密切相关
- 类型分为非常量和常量,一个常量对象必须初始化,而且一旦初始化其值就不能再改变
- 可以定义复合类型,如指针和引用,复合类型定义时以其他类型为基础
本章术语表
- [x] 地址是一个数字,根据它可以找到内存当中的任何一个字节
- [x] 别名声明为另外一种类型定义一个同义词,使用`名字=类型`的格式将名字作为该类型的同义词
- [x] 布尔值,字符,整数,浮点数等内置类型
- [x] 一种数据结构,存放着一组未命名的对象,可以通过索引来访问这些对象
- [x] 是一个类型说明符,通过变量的初始值来推断变量的类型
- [x] 类型说明符,可用const修饰,在声明语句中位于声明符之间,基本类型提供了最常见的数据类型,以此为基础构建声明符
- [x] 绑定是令某个名字与给定的实体关联在一起,使用该名字也就是使用该实体,例如引用
- [x] 内存中可寻址的最小单元,大多数机器的字节占8位
- [x] 是一种类型,它的定义以其他类型为基础
- [x] 类的组成部分
- [x] 是一种类型修饰符,用于说明永不改变的对象,const对象一旦定义就无法再赋新值,所以必须初始化
- [x] 一种指针,它的值永不改变(顶层const)
- [x] 一种习惯叫法,指向常量的引用
- [x] 能在编译时计算并获取结果的表达式
- [x] 一种类型的值变为另外一种类型的值得过程,C++语言支持内置类型之间的转换
- [x] 组成对象的数据元素,类的每个对象都有类的数据成员的一部分拷贝,数据成员可以在类内部声明时初始化
- [x] 是声明的一部分,包括被定义的名字和类型修饰符,其中类型修饰符可以有也可以没有
- [x] 当对象未被显式的赋予初始值时执行的初始化行为,由类本身负责执行的类对象的初始化行为,全局作用域的内置类型对象初始化为0,局部作用域的对象未被初始化即拥有未定义的值
- [x] 为某一种特定类型的变量申请存储空间,可以选择初始化该变量,名字必须在定义或声明之后才能使用
- [x] 字符,特别是那些不可打印字符的替代形式,转义以反斜线开头,后面紧跟一个字符,或者不多于3个八进制数字,或者字母x加上1个十六进制数
- [x] 位于其他所有作用域之外的作用域
- [x] 使用预处理变量防止头文件被某个文件重复包含
- [x] 组成名字的字符序列,标识符对大小写敏感
- [x] 在声明类的数据成员时同时提供的初始值,必须置于等号右侧或者花括号内
- [x] 名字在当前作用域内可见
- [x] 变量在定义的同时被赋予初始值,变量一般都应该被初始化
- [x] 嵌套在其他作用域之内的作用域
- [x] 利用花括号把一个或多个初始值放在一起的初始化形式
- [x] 是一个不能改变的值,如数字,字符,字符串等,单引号内的是字符字面值,双引号内的是字符串字面值
- [x] 块作用域的习惯叫法
- [x] 一个不属于顶层的const,类型如果由底层常量定义,则不能被忽略
- [x] 类的组成部分
- [x] 不具有可见形式的字符,如控制符,退格,换行符等
- [x] 值为0的指针,空指针合法但是不指向任何对象
- [x] nullptr是表示空指针的字面值常量
- [x] 是内存的一块区域,具有某种类型,变量是命名了的对象
- [x] 嵌套着别的作用域的作用域
- [x] 是一个对象,存放着某个对象的地址,或者某个对象存储区域之后的下一地址,或者0
- [x] 是一个指针,存放着某个常量对象的地址,指向常量的指针不能用来改变它所指对象的值
- [x] 在C++编译过程中执行的一段程序
- [x] 由预处理器管理的变量,在程序编译之前,预处理器负责将程序的预处理变量转换成它的真实值
- [x] 某个对象的别名
- [x] 是一个引用,不能用来改变它所绑定的对象的值,对常量的引用可以绑定常量对象,或者非常量对象,或者表达式结果
- [x] 是程序的一部分,在其中某些名字有意义,C++有以下几级作用域
- 全局(global): 名字定义在其他所有作用域之外
- 类(class): 名字定义在类内部
- 块(class): 名字定义在块内部
- [x] 名字从声明位置开始直至声明语句所在的作用域末端为止都是可用的
- [x] 把程序分割为多个单独文件的能力
- [x] 保存正数,负数或0的整型(不能是小数)
- [x] 是一种库类型,表示可变长字符序列
- [x] 用于定义结构体的关键字
- [x] 编译器在计算表达式结果时创建的无名对象,为某些表达式创建一个临时值,则此临时值将一致存在知道包含有该表达式的最大的表达式计算完成为止
- [x] 规定某对象的值不能改变,const
- [x] 是另一个类型的同义词,通过关键字typedef或别名声明语句来定义
- [x] 是一个过程,编译器检查程序使用某些给定类型对象的方式与该类型的定义是否一致
- [x] 即C++语言没有明确规定的情况,不论是否有意为之,未定义行为都有可能引发难以追踪的运行错误,安全问题和可移植性问题
- [x] 变量已定义但未被赋予初始值,一般来说,试图访问未初始化的变量的值将引发未定义行为
- [x] 保存大于等于零的整型
- [x] 命名的对象或引用,C++语言要求变量要先声明后使用
- [x] 可以指向任意非常量的指针类型,不能执行解引用操作
- [x] 是一种有特殊用处的类型,既无操作也无值,不能定义一个void类型的变量
- [x] 在指定机器上进行整数运算的自然单位,一般来说,字的空间足够存放地址,32位机器上的字通常占4个字节