基本内置类型
含无符号类型的表达式
隐式类型转换顺序:
如果表达式中既有带符号类型和无符号类型,带符号数会自动转换为无符号类型;
字面值常量
'a'
:字符字面值,hi
:字符串字面值
20
十进制,024
八进制,0xff
十六进制,\x4d
和\77
均表示M
指定常量的类型:
前缀 | 含义 | 类型 |
---|---|---|
u | unicode16字符 | char16_t |
U | unicode32字符 | char32_t |
L | 宽字符 | wchar_t |
u8 | utf-8 | char |
整形字面值 | 浮点型字面值 | " | |
---|---|---|---|
后缀 | 最小匹配类型 | 后缀 | 类型 |
u,U | unsigned | f,F | float |
l,L | long | l,L | long double |
ll,LL | long long |
L'a' //宽字符型 u8"hi!" //utf-8 1E-3F //float 3.14 //long double
变量
列表初始化
使用花括号来初始化成为列表初始化;
1 | int a = 0; |
如果使用列表初始化且初始值存在丢失信息的风险,则编译器会报错;但是,使用普通的列表初始化并不会出错;
1 | double a = 3.14; |
分离式编译
C++语言允许分离式编译,该机制允许将程序分割为若干个文件每个文件可被独立编译;
声明与定义
1 | extern int i; //声明i而非定义 |
extern语句若包含初始值也就变成了定义
引用
引用必须被初始化,int &a
是错误的,定义引用时,程序把引用和它的初始值一直绑定在一起,一旦初始化完成,引用和它的初始化值对象一直绑定在一起,;因为无法令引用重新绑定到另外一个对象,因此引用必须初始化;
引用本身不是一个对象,因此不能定义引用的引用;
1 | int &val1 = 10; //错误,引用类型的初始值必须是一个对象,这个非常关键 |
1 |
|
int *& 与int &*
从内往外看,int *&
定义的是指针的引用,int &*
定义的是引用的指针,而引用又不是对象,因此没有指针;所以第二种写法严格来说是错误的;
void *
void *
是一种特殊的指针类型,可用于存放任何对象的地址,因此对于它的地址中存放着一个什么类型的对象是不知道的;
并且以void *
视角访问内存,只能访问到地址,而不能访问到具体地址的对象;
令注:在c++/c中进行指针类型转换不是一件随便的事情;
1 | int i = 10; |
const
const
对象必须进行初始化;
1 | //这条语句是错误的 |
const
类型的对象只能执行不改变其内容的操作;如算数运算,转换成一个布尔值;
const与初始化
如果用一个对象去初始化另一个对象,则它们是不是const
都无所谓;
1 | int i = 42; |
ci
的const
特征仅仅在执行修改它的操作时才发挥作用;
const的引用
可以把引用绑定到const
上;对const
的引用常称为“常量引用”;
1 | const int ci = 1024; |
虽然非常量引用不允许绑定到常量上,但是常量引用允许绑定到非常量上
初始化与对 const 的引用
1 | double dval = 3.14; |
上面两条语句其实本质是这样的:
1 | double dval = 3.14; |
下面两条语句是错误的:
1 | const int &ri = 10; |
非 const 与 const 引用同时绑定
1 | int i = 42; |
const 与指针
与引用相似,要存放一个 const
类型变量的地址,只能用指向 const
类型变量的指针;但是指向常量的指针没有规定其所指对象必须是常量;
1 | int num = 0; |
constexpr
声明为 constexpr
的变量一定是一个常量,而且必须用常量表达式初始化;
1 | constexpr int mf = 20; // 20 是常量表达式 |
对于 constexpr
的声明中,它仅对指针有效,对指针所指对象无关;
null与nullptr
首先需要明确, null
是无类型的,而 nullptr
是 nullptr_t
类型的;
在c++中不能将void *
类型转换成其他类型,在c++中,在stddef.h中null
是这样定义的:
1 |