数据类型告诉我们数据的意义以及操作
2.1 基本内置类型
2.1.1 算术类型
整形(包括字符和bool类型)、浮点型
C++中只规定了内置类型的最小尺寸
2.1.2 类型转换
尤其注意带符号和不带符号之间的转换
2.1.3 字面值常量
(literal)eg:42|'a'|"Hello world!"|nullptr|false
转义序列
eg:\n|\t|\\|\?
可以通过加前后缀的方法指定字面值常量的类型
L'a'|42ULL
2.2变量
提供一个具名的、可供程序操作的存储空间
2.2.1 变量定义
类型说明符 一个多个变量名(逗号隔开);
int a,b,c;
对象和变量一般互换使用,对象通常指的是一块能存储数据并具有某种数据类型的内存空间.
对变量初始化是习惯必要的,初始化与赋值不同
用列表初始化可以方便的检测出初始值是否用丢失信息的风险eg: ing a={0};
默认初始化:定义与任何函数体外的变量被初始化为0,其它值被默认初始化(初始值是多少?),例外情况:定义于函数体内的内置类型变量不会被初始化。因此对变量初始化是习惯必要的
2.2.2 变量声明和定义
C++支持分离式编译,允许程序分割为若干文件,每个文件可以独立编译,如何在文件间共享代码?
声明使名字被程序所知,一个文件想要使用别处定义的名字就必须包含对那个名字的声明。定义创建了与名字相关联的实体
声明 extern int i;
定义 int j;
只要显示初始化变量就看作定义变量,如果想在多个文件中共用同一个变量,声明变量必须分离,声明能有多次,定义只能有一次
2.2.3 标识符
由字母、数字、下划线组成,必须以字母、下划线开头
注意使用命名规范提高程序可读性
变量名用小写字母,类名用大写字母开头、多个单词间隔开
2.2.4 作用域
C++作用域用{}分隔
2.3复合类型
基于其他类型定义的类型,这里重点介绍引用和指针
2.3.1 引用
左/右值引用,右值引用是对内置类讲的,这里指左值引用.引用类型必须和其引用对象类型一致
int ival=1;
int &refVal=ival;
int &refVal4=10;\\error 引用类型初始值必须为一个对象
引用必须被初始化,因为引用只是给另外一个已经存在的对象起了别名,所以引用必须绑定.同理没有引用的引用,一旦绑定就不能绑定到其他对象
2.3.2 指针
pointer 指向另外一个类型的负荷类型,和应用类似实现了其他对象的间接访问,但是1 指针本身是一个对象;2 指针无需定义时赋值,当然建议初始化。
int *p1,*p2;//指针定义
double dval,*dp2;
dp2=&dval;
int ival=42;
int *p=&ival;//取地址符 &获取对象地址
cout<<*p;//解地址符*
p=&dval;//error
指针非常复杂以后接触到再说
空指针
int *p1=nullptr; //等价于 int *p1=0;
int *p2=0; //#include cstdlib
int *p3=NULL;//等价于 int *p3=0;
nullptr是C++11刚引入的,是一种特殊类型的字面值,可以转换为任意其他指针类型,最好使用nullptr而不是NULL。
赋值
和引用不同,指针和其他变量一样可以给指针赋值。
void* 指针
是一种特殊的指针类型,可以存放任意对象地址,void*指针中存放了一个地址,里面具体放了什么类型对象,并不知道。
void *视角看内存空间就是内存空间,没办法访问内存空间对象.
double obj=3.14;
int ival=3;
void *pv=&obj;
pv=&ival;
2.3.3 理解符合类型的申明
int *p;//*修饰的是p,并不是int
//类型修饰符只是声明符的一部分
int *p1,*p2;
指向指针的指针
int **p1,***p1;//依次类推
int ival=1024;
int *pi=&ival;
int **pi=π
不能定义指向引用的指针,但是存在指针的引用
理解类型是什么,最简单的方法是从右到左阅读r的定义,离变量名最近的符号对变量类型有最直接的影响
int i=21;
int *p;
int *&r=p;//对指针p的引用
r=&i;//相当于p=&i
*r=0;//后果i=0
2.4 const
const 标志变量类型是常量,必须初始化。
因为在编译时,会把出现这个常量的地方,全部替换对应初始值.
const int buff_size=1024;
注意 const对象被设定为仅在文件内有效
如果想要在文件间共享,如果是常量表达式,使用extern声明就好。
如果不是常量表达式,则需要在不论在定义还是声明都是用extern
extern const int bufsize
同时在具体定义时使用
extern const int bufsize=fun();
2.4.1 对常量的引用
必须使用常量类型的引用来引用常量,常量引用只是对引用可以参与的操作做了限制
const int ci=1;
const int &r1=ci;
常量引用可以绑定非常量对象,非常量引用并不能绑定常量对象
double dval=3.14;
const int &ri=dval;
//会发生以下事件
const int temp=dval;
const &ri=temp;
//显然如果是对非常量引用这么操作是没有意义的,
//因为如果是非常量引用,
//你肯定是想改变dval的值,显然是不可能的,
//所以只有常量引用才会过编译
2.4.2 指针和const
指向常量的指针,同常量引用类似,都是指向对象的常量指针或者引用,操作受到限制。指向的对象是不是常量,并不关心。
常量指针 const指针 不允许改变指针本身的值,但是如果指向的不是常量,就可以改变指针指向的值
int num=9;
int *const curErr=#
注意与const int *p的区别
2.4.3 顶层const
top-level const 表示指针本身是常量,一般化 表示任意对象是常量
low-level const 表示指针指向的对象 是常量,一般化 与指针和引用等符合类似的基本类型部分相关,底层const拷贝时,拷出对象必须具有相同的const资格,或者两个对象的数据类型可以相互转换,譬如非常量转换常量
2.4.4 常量表达式与constexpr
- 值不会变
- 在编译是就可以得到计算结果的表达式
C++11新标准规定使用constexpr声明变量有编译器验证变量是否是一个常量表达式
字面值类型
可以被定义成constexpr的类型,称为字面值类型,literal type
指针和constexpr
constexpr声明中如果定义一个指针,constexpr会把指针变为顶层const
constexpr int *p=nullptr;\\一个顶层非底层const指针