1.基本内置类型
(1)算术类型(arithmetic type)
整型(integral type):包括字符/bool类型
浮点型(floating-point type)
C++算术类型
类型 | 含义 | 最小尺寸 |
bool | 布尔类型 | 未定义 |
char | 字符 | 8位 |
wchar_t | 宽字符 | 16位 |
char16_t | Unicode字符 | 16位 |
char32_t | Unicode字符 | 32位 |
short | 短整型 | 16位 |
int | 整型 | 16位 |
long | 长整型 | 32位 |
long long | 长整型 | 64位 |
float | 单精度浮点数 | 6位有效数字 |
double | 双精度浮点数 | 10位有效数字 |
long double | 扩展精度浮点数 | 10位有效数字 |
注:Unicode是为了解决传统的字符编码方案的局限而产生的,它为每种语言中的每个字符设定了统一并且唯一的二进制编码,以满足跨语言、跨平台进行文本转换、处理的要求。
注:基本的字符类型是char,一个char的空间应确保可以存放机器基本字符集中任意字符对应的数字值,也就是说,一个char的大小和一个机器字节一样。wchar_t,char16_t,char32_t属于扩展字符集(为了表示更多的欧洲常用字符对ASCII进行了扩展)。
内置类型的机器实现
字节(byte):可寻址的最小内存块
字(word):存储的基本单元
大多数机器以2的整数次幂个比特作为块来处理内存(每个bit非0即1),字节由8比特构成,字由32或64比特构成(即4或8字节)。将内存中的每个字节与一个数字(即地址,address)关联起来,从而可以使用某个地址来表示从这个地址开始的大小不同的比特串。
带符号类型与无符号类型
除bool和扩展的字符型之外,其他整型可以划分为带符号的(signed)和无符号的(unsigned):
字符型:char,signed char,unsigned char(char根据编译器的不同会表现为后两种中的一种)
其他整型:均为带符号的,无符号需在前面加上unsigned
建议:1)当明确知晓数值不可能为负数时,选用unsigned类型
2)使用int执行整数运算,若数值超过int的表示范围,则选用long long
3)在算数表达式中不要使用bool或char,只在存放字符或布尔值时才使用它们
4)执行浮点数运算时选用double而非float
类型转换
bool b = 42; //b = true,bool值实际上非0即1
int i = b; //i = 1
i = 3.14; //i = 3
double pi = i; //pi = 3.0
unsigned char c = -1; //c = 255
signed char c2 = 256; //c2值未定义
注:赋给无符号类型一个超出它表示范围的值时,结果是初始值对无符号类型表示数值总数取模后的余数;赋给带符号类型一个超出它表示范围的值时,结果是未定义的。
字面值常量(literal)
每一个值都为字面值常量,均对应一种数据类型,字面值常量的形式和值决定了它的数据类型。
通过添加前缀和后缀,可以改变整型/浮点型/字符型字面值的默认类型:
后缀 | 最小匹配类型 |
u or U | unsigned |
l or L | long |
ll or LL | long long |
后缀 | 类型 |
f or F | float |
l or L | long double |
前缀 | 含义 | 类型 |
u | Unicode16字符 | char16_t |
U | Unicode32字符 | char32_t |
L | 宽字符 | wchar_t |
u8 | UTF-8(仅用于字符串字面常量) | char |
注:布尔类型的字面值为true或false,指针字面值为nullptr。
转义序列
换行符 | \n |
横向制表符 | \t |
纵向制表符 | \v |
反斜线 | \\ |
回车符 | \r |
退格符 | \b |
问号 | \? |
进纸符-走纸换页 | \f |
报警符(响铃符)-蜂鸣器响 | \a |
双引号 | \" |
单引号 | \' |
(2)空类型(void)
空类型不对应具体的值,仅用于一些特殊场合,比如当函数不返回任何值时使用空类型作为返回类型。
2.变量
(1)变量定义
列表初始化(C++11新标准)
int a = 0;
int a = {0};
int a{0};
int a(0);
若使用long double的值初始化int变量:
long double ld = 3.1415926;
int a{ld}, b = {ld}; //错误,转换未执行(存在丢失信息的危险时花括号定义不执行)
int c(ld), d = ld; //正确,转换执行,且确实丢失了部分值
默认初始化:若定义变量时未指定初始值,则变量会被默认初始化。定义于任何函数体之外的变量被初始化为0,定义在函数体内部的内置类型变量将不被初始化(绝大多数类支持无须显式初始化而定义对象初始化为一个空串)。
(2)变量声明
变量定义:创建与名字关联的实体
变量声明:使得名字为程序所知,从而可以使用别处定义的名字,实现分离式编译
区别:定义申请了存储空间,也可能会为变量赋一个初始值;而声名不能显式初始化变量
声明的形式:
extern int i;
(3)标识符(identifier)
由字母/数字/下划线组成,其中必须以字母或下划线开头。
注: C++关键字为语言所保留,不能用作标识符;标准库也保留了一些名字:
1)用户自定义的标识符中不能连续出现两个下划线
2)不能以下划线紧连大写字母开头
3)定义在函数体外的标识符不能以下划线开头
变量命名规范:
1)变量名一般用小写字母
2)用户自定义的类名一般以大写字母开头
3)标识符由多个单词组成时,单词间应有明显区分如加下划线或大小写
(4)名字的作用域(scope)
名字的有效区域始于名字的声明语句,以声明语句所在的作用域末端为结束。(C++中大多数作用域都以花括号分隔)
全局作用域(global scope):名字定义在函数体之外,在整个程序的范围内都可使用
块作用域(block):名字定义在某个函数或某个循环语句内,只在其所在花括号中有效
嵌套的作用域(作用域能彼此包含,分为内层/外层作用域)
#include <iostream>
int reused = 42; //reused拥有全局作用域
int main() {
int unique = 0; //unique拥有块作用域
std::cout << reused << " " << unique <<std::endl; //42 0
int reused = 0; //新建局部变量reused,覆盖了同名的全局变量
std::cout << reused << " " << unique <<std::endl; //0 0
std::cout << ::reused << " " << unique <<std::endl;//42 0
3.复合类型
(1)引用(reference,实指左值引用,lvalue reference)
引用:为对象起了另一个名字
定义引用时,程序把引用和它的初始值绑定,而非将初始值拷贝给引用(引用类型的初始值必须是一个对象,而不能是一个定值)
int a = 1;
int &b = a;
a = 2;
std::cout << b << std::endl;
上述代码的输出结果为2,说明引用b的值始终与a值绑定,改变a的值即改变b的值;同时,改变b的值也即改变a的值。
(2)指针(pointer)
指针:存放某个对象的地址
指针初始化:
int *p = &a;
指针值:
1)指向一个对象
2)指向紧邻对象所占空间的下一个位置
3)空指针(没有指向任何一个对象,nullptr)
4)无效指针(上述情况之外的其他值)
4.const限定符
const:将一个变量限定定义为常量,任何试图对其赋值的行为都将引发错误
const对象在定义时必须初始化(默认情况下,const对象被设定为仅在文件内有效;若需要只在一个文件中定义const而在其他多个文件中声明并使用它,则对于const变量不管声明还是定义都添加extern关键字)
对const的引用
const int c =1024;
const int &c1 = c; //正确
int &c2 = c; //错误:试图让一个非常量引用指向一个常量对象
int i = 42;
const int &i1 = i; //正确:允许将const int&绑定到一个普通int对象上,但不允许通过i1修改i的值
注:指向常量的指针不能用于改变其所指对象的值,但所指对象也不一定需要是一个常量。
const指针
int num = 0;
int *const ptr = # //ptr将一直指向num
顶层const:指针本身是一个常量(执行对象的拷贝操作时无影响)
底层const:指针所指的对象是一个常量(拷贝时受限)
int i = 0;
int *const p1 = &i; //顶层const
const int ci = 42; //顶层const
const int *p2 = &ci;//底层const
const int &r = ci; //底层const
const int *const p3 = p2;//靠右的const是顶层const,靠左的const是底层const
常量表达式(constexpr)
constexpr int mf = 20;
constexpr int limit = mf + 1;
5.处理类型
类型别名(type alias):某种类型的同义词
定义类型别名:
typedef double wages;//wages是double的同义词
typedef wages base, *p;//base是double的同义词,p是double*的同义词
别名声明:
using SI = Sales_item; //SI是Sales_item类的同义词
auto类型说明符:编译器能够代替人分析表达式所属的类型
auto item = val1 + val2;
decltype类型指示符:推断要定义的变量的类型,但不用该表达式的值初始化变量
const int ci = 0, &cj = ci;
decltype(ci) x = 0; //x的类型是const int
decltype(cj) y = x; //y的类型是const int&, y绑定到变量x上
decltype(cj) z; //错误:z是一个引用,必须初始化
6.自定义数据结构
定义类型struct(同C语言中的结构体),一般写在头文件中
预处理器概述:
1)预处理器读到#include时会用指定的头文件内容代替#include
2)头文件保护符(header guard)依赖于预处理变量,使用头文件保护符能够有效地方志重复包含的发生
#ifndef SALES_DATA_H //检查该预处理变量是否已经定义,未定义时为真
#define SALES_DATA_H //把一个名字设定为预处理变量
#include <string>
struct Sales_data {
std::string bookNo;
double revenue = 0.0;
} ;
#endif //结束操作
注:预处理变量无视C++中关于作用域的规则