2.1基本内置类型
2.1.1算术类型
C++的基本内置类型包括算数类型和空类型,空类型就是void,算术类型我从原书中截下来放在下面:
从上表我们可以得知C++规定int至少和short一样大,long至少和int一样大,longlong至少和long一样大.
其中char(字符)类型支持国际化,所以char会确保可以放下任意字符对应的数字值,char的大小和一个机器字节一样.
在类型名前加上 unsigned 可以得到对应的无符号类型,例如 int 为整型, unsigned int 为无符号整型,无符号类型不能为负数.
书中推荐当明确知道数值不会为负数时,选用无符号类型.
当使用int做运算时,若范围有可能超过int,那么则选用longlong而不是long,以为long的取值范围有可能和int是一样的.如果用到的整数是一个不大的,那么可以选用 unsigned char 或是 signed char (以前我玩单片机的时候会为了节约内存把 int 改用为 unsigned char ).
2.1.2类型转换
不能给一个无符号的对象赋一个负值,正常人都不会这么干,但是我们有可能在做运算的时候把无符号操作成负数,这是应当注意和避免的.
书中提示不要混用带符号类型和无符号类型.
2.1.3字面量常量
C++中包含的转义字符如下:
虽然它看起来有两个字符,但转义字符被当作一个字符使用(即一个char).
给对象赋值时,若给出一个小数,那么默认为double类型,单引号包裹的内容默认为字符类型,双引号包裹的内容默认为字符串类型……通过添加字面量前缀或后缀可以改变字面量的默认类型:
如果使用long类型时,后缀使用L,因为小写的l会和数字1混淆.
2.2变量
2.2.1变量定义
C语言中没有string字符串类型,C++中的string类型完整的写法是std::string,因为string是在命名空间std中定义的,目前只需要知道string是一种表示可变长字符序列的数据类型即可.
在C++中初始化和赋值是两种完全不同的操作,初始化是创建变量时赋予一个初始值,赋值则是把对象当前的值擦除,用一个新值来替代.
C++中初始化有好几种不同类型,以下四种方式都可以将整型变量初始化为0;
int a=0; //我最常用
int b={0};
int c{0};
int c(0);
在C++11新标准中,使用花括号{}来初始化变量得到全面应用(包括vector在内的各种容器都可以使用花括号来初始化),这种方式被称为列表初始化.
2.2.2变量声明和定义的关系
C++支持分离式编译机制(就是分文件编写),为了支持这一特性,C++中声明与定义区分.声明使得名字为程序所知,定义负责创建与名字(名字这个概念在书中反复被提到)关联的实体.
如果想声明一个变量但不定义,则在变量名前添加关键字 extern,而且不要显式地初始化变量,任何包含显式初始化的声明都为定义.在函数体内部如果试图初始化一个有extern标记的变量将会引发错误.变量只能被定义一次,但可以被多次声明.
extern int i; //声明i但没定义
int i; //声明i并且定义
2.2.3标识符
书中建议的变量命名规范如下(个人命名标识符喜欢驼峰命名法):
2.2.4名字的作用域
作用域是程序的一部分,C++中大多数作用域用花括号{}来分隔.同一个名字在不同的作用域可能指向不同的实体.名字的有效区域始于命名语句,结束与命名语句所在的作用域结尾.main函数定义与所有花括号外,其他与main一样定义在函数体之外的名字都拥有全局作用域,即整个程序都可以使用.函数内部不推荐使用和全局变量同名的变量,如果真的用到了同名的变量,则优先使用内部的变量(就近原则),但容易混淆.
2.3复合类型
2.3.1引用
引用的全称是"左值引用".定义引用时,程序把引用和它的初始值绑定在一起,引用即是别名,引用绑定后,修改绑定即是修改原值.引用并非对象,它只是为一个已经存在的对象所起的另一个名字.由于引用本身不是对象,所以不能定义引用的引用,并且一般情况下引用的类型要和所绑定的类型严格匹配.
2.3.2指针
指针存放的是对象的地址,初始化指针时,可以用取地址符号(&)来给指针赋值,也可以用解引用符(*)(解引用符只适用于已经明确指向了某个对象的有效指针)来访问指针所指向的值.由于引用不是对象,所以不能定义指向引用的指针.一般情况下指针的类型要和它指向的对象保持类型一致(这一点和引用一样)
定义空指针有以下几种方法(暂时不懂指针该指向哪里的时候就初始化为空指针)
int *p=nullptr;
int *p=0;
int *p=NULL; //这种方法需要#include<cstdlib>
最常用的并且推荐的是使用nullptr(C++11新标准),不推荐使用NULL.
void*是一种特殊的指针类型,可以用于存放任意对象的地址.
2.4const限定符
const修饰的对象为常量,创建后,值不能再修改,所以const对象必须初始化.
2.4.1const的引用
const修饰引用,我们称之为对常量的引用,与普通引用不同的是,对常量的引用不能被用作修改它所绑定的对象.
2.4.2指针和const
与引用不同的是指针是一个对象,所以指针本身可以被const修饰变成指针常量,指针常量不能修改指向.
const int *p; //不能改变所指向的地址指向的值
int *const p; //不能改变指向
2.4.3顶层const
顶层const可以表示任意的对象是常量.底层const则与指针和引用等复合类型的基本类型部分有关.
我个人的理解是const修饰的是常量则为顶层const,const修饰的间接指向常量则为底层const.书中简单提了一下顶层const和底层const的这个概念(后续还会出现,想详细了解的可以查看原书或者去百度),我觉得挺绕的.
2.4.4constexpr
C++11新标准规定,允许将变量声明为constexpr类型以便编译器验证变量的值是否为常量表达式,所以声明为constexpr的变量一定是一个常量,而且必须用常量表达式来初始化.我不太懂这个的用法,但是书中说:
一个constexpr指针的初始值必须为nullptr或者0;
2.5处理类型
2.5.1类型别名
变量可以用引用来起别名,类型也可以有别名,有两种方法,第一种是传统的关键字typedef,第二种是别名声明:
typedef int MYINT; //MYINT是int的别名(方法一,C语言中也是如此)
using MYINT = int //MYINT是int的别名(方法二,C++11新标准)
2.5.2auto类型说明符
C++11新标准引入auto类型说明符,可以当作数据类型使用,而它具体是什么数据类型是编译器由初始值判断的,所以auto类型的变量必须有初始值.
2.5.3decltype类型指示符
C++11新标准引入decltype,可以返回操作数的数据类型.使用时在括号中放入具体的值,然后编译器由值来判断具体数据类型,这点和auto类型,但decltype可以使得变量不必初始化而仅仅是声明
decltype(1) a; //a的类型为int
decltype('a') b; //b的类型为char
decltype(('a')) c; //c的类型为char& ,但是这么定义是错误的,因为引用必须被初始化
2.6自定义数据结构
本小节书中举的例子是struct,由于和C语言一样,我就不多赘述了.
值得拎出来强调的是头文件保护符:
#ifndef TEST_H
#define TEST_H
/*
* 具体的头文件内容
*/
#endif
写头文件的时候无论怎么样都最好加上一段包裹住代码,以防止重复包含头文件.