变量
基础标准
* 类型
基本类型(9种)
布尔型(bool) 字符型(char) 宽字符型(wchar_t ) 短整型(short) 整型(int) 长整型(long) 单精度浮点型(float) 双精度浮点型(double) 长双精度浮点型(long double)
布尔型
布尔型(bool) - true/false
字符型 - 转义字符
字符型(char) 'a'
宽字符型(wchar_t ) L'a'
整型 - 四种表达方式(二进制,八进制,十进制,十六进制)
短整型(short)
整型(int) 1(默认为int)
长整型(long) 1L或者1l
浮点型 - 两种表达方式(十进制和科学计数法)
单精度浮点型(float) 1.1F或1.1f FLT_EPSILON
双精度浮点型(double) 1.1(默认为double)
长双精度浮点型(long double)
复合类型(7种)
数组 指针* 引用& 共用体(union) 结构体(struct) 枚举(enum) 类(class)
☞ 指针 - 与引用区别
☞ 引用 - 引用折叠
非常量左值引用、常量左值引用、非常量右值引用、常量右值引用
以int为例:int&,const int&,int&&,const int&&
☞ 结构体 - 大小
遵循两个原则+处理器架构+编译器
两个原则
1.结构体每个成员的偏移量是该成员最大对齐方式的整数倍,即offset(member)/align(member)=整数;
2.结构体总大小是该结构体最大对齐方式的整数倍,即sizeof(struct)/align(struct)=整数;
编译器
/* 编译器指定最大对齐方式为1 */
#pragma pack(push)
#pragma pack(1)
// 定义结构体
#pragma pack(pop)
自身对齐值:基本数据类型的变量就是其本身所占字节大小,复合类型的最大对齐值;
指定对齐值:由#pragma pack(value)指定的对齐值value;
有效对齐值:自身对齐值和指定对齐值中较小的值。
特殊类型
空void 别名typedef 别名using
* 标识
数字、字母和下划线组成,不能以数字开头,大小写敏感
* 限定
static
extern 默认
mutable
const - 默认为static const,如需外部引用需显式指定extern const
volatile - 易变性,不可优化性,顺序性(保证编译器语句顺序,不能保证cpu顺序执行)
unsigned(U/u)
类型推导(c++11)
auto
类型指示符,提示编译器对此类型的变量做类型的自动推导。
推导规则:
- 当不声明为指针或者引用时,auto的推导结果和初始化表达式抛弃引用和cv限定符后的类型一致;
- 当声明为指针或者引用时,auto的推导结果将保持cv属性;
// 不声明指针或者引用
int i0 = 1;
int& i1 = i0;
auto i2 = i1; // auto -> int (初始化表达式类型为int&,抛弃了引用后是int)
// 声明指针或者引用
int i3 = 1;
const int& i4 = i3;
auto& i5 = i4; // i5 -> const int& (初始化表达式类型为const int&,保留const属性)
推导限制
- 函数参数类型
- 模板
- 结构体非静态成员
decltype
推导出表达式的类型,编译期完成
推导规则:
- 标识符和类访问表达式,decltype(exp)和exp表达式类型一致;
- 函数调用,若是非类类型纯右值忽略cv,否则跟返回值保持一致;
- 其他运算表达式,若是左值decltype(exp)和exp类型的左值引用一致,否则和exp类型一致;
初始化列表
普通数组
POD(平凡和标准布局)
判断:std::is_pod<T>::value
好处:
- 字节赋值,可以使用memset和memcpy等内存操作
- 与c内存布局兼容,C和C++直接操作安全
平凡 std::is_trivial<T>::value
平凡的默认构造函数和默认析构函数
平凡的默认拷贝构造函数和默认移动构造函数
平凡的默认拷贝赋值函数和默认移动赋值函数
无虚函数和虚基类
标准布局 std::is_standard_layout<T>::value
有待完善。。。
容器和std::initializer_list构造的类
类型转换
static_cast
①用于类层次结构中基类(父类)和派生类(子类)之间指针或引用的转换。
进行上行转换(把派生类的指针或引用转换成基类表示)是安全的;
进行下行转换(把基类指针或引用转换成派生类表示)时,由于没有动态类型检查,所以是不安全的。
②用于基本数据类型之间的转换,如把int转换成char,把int转换成enum。这种转换的安全性也要开发人员来保证。
③把空指针转换成目标类型的空指针。
④把任何类型的表达式转换成void类型。
dynamic_cast
沿继承层级向上、向下及侧向,安全地转换到其他类的指针和引用
主要用于执行“安全的向下转型(safe downcasting)”,也就是说,要确定一个对象是否是一个继承体系中的一个特定类型。支持父类指针到子类指针的转换,这种转换时最安全的转换。它是唯一不能用旧风格语法执行的强制类型转换,也是唯一可能有重大运行时代价的强制转换。
const_cast
一般用于强制消除对象的常量性
reinterpret_cast
是特意用于底层的强制转型,导致实现依赖(就是说,不可移植)的结果,例如,将一个指针转型为一个整数。
PS:内部变量 __cplusplus __FILE__ __LINE__ __FUNCTION__ __func__ __DATE__ __TIME__
操作符
算术操作符
+加 -减 *乘 /除 %求余 ++自增 --自减
重载 (--运算符类似)
▷ 类内部重载
classname operator++() 前置++(++a)
classname operator++(int) 后置++
▷ 全局重载
classname operator++(classname& obj) 前置++
classname operator++(classname& obj, int) 后置++
关系操作符
>大于 <小于 >=大于等于 <=小于等于 !=不等于 ==等于
逻辑操作符
&&与 ||或 !非
位操作符
& | ^ ~ >> <<
<< 如果是无符号类型,移位补0,如果是有符号,正数补0,负数补1
ps: 移位需注意变量类型,以及正负
赋值运算符
= += -= *= /=%= &= |= ^= <<= >>=
= 只能被类的成员函数重载
箭头操作符
条件操作符
? :
sizeof操作符
不能重载的操作符
转换操作符
例如:operator double(); // 无返回值
其他操作符
- 位操作符 & | ^ ~
- 成员操作符 . ->
- 条件操作符 ? :
- 流操作符 <<和>>
- 函数操作符 ()
- 下标操作符 []
- 类型操作符 用于类的类型转换
- 逗号操作符 ,
- 域操作符 ::
- sizeof操作符
- throw操作符
- typid操作符
- 转换操作符 *_cast
- .*和->*操作符
- new和delete操作符
- 占位操作符 std::ignore,用于元组解包,严格来讲不算运算符