变量 和 基础类型
基本内置类型
- 无符号数 unsigned
当一个负数被赋值给一个无符号数,结果为该负数加上无符号数的模 (2^32)
表达式中既有unsigned又有int,int将被转为无符号数再运算
int a = -1;
unsigned b = 1; // 4 bytes
std::cout << a + b; // 4294967295 UINT_MAX
变量
- 初始化
默认初始化
全局的、静态的变量将被初始化为0,任何函数体内的内置变量不会被初始化
列表初始化 [C++11]
使用花括号初始化,如果存在信息丢失风险(narrowing conversion),将报错
int a = 0;
int a = {0};
int a{0};
int a(0);
// int a{1.1}; // 错
- 声明和定义
声明规定了类型和名字,定义创建了与名字相关联的实体
变量只能定义一次,但可以被声明多次
试图初始化一个extern标记变量将报错: extern int i = 0; // error
// test.h
int i = 1;
// main.cpp
extern int i; // 只是声明了i
int j; // 声明并定义了j
复合类型
- 指针和引用
- 引用不是对象,只是别名,不存在引用的引用;指针是对象,可以有指针的指针
- 引用创建同时需要赋值;指针无须定义时初始化
- 引用不能改变指向的对象;不是指针常量就可以改变指向
- 指针的引用
int *&ref;
;不可以有引用的指针
- void*
存放放任意对象的地址,但不能访问内存空间中的该对象,因为不知道类型
- 复合类型的声明
声明语句通常为: 数据类型 + 声明符列表
如: int a, b, c;
复合类型 指针、引用的声明
如: int *a, &b;
其中int为基础数据类型,而* &
称做类型修饰符,其实是声明符的一部分,建议采用类型修饰符与变量名贴紧的写法,防止出现int* a, b;
误认为b为指针 写法没有对错,选择并坚持一种写法
多个类型修饰符时,采用从右往左的方式阅读方式,如:int *&a
先&确定a为一个引用,其次是*说明是指针的引用,最后基础数据类型int,a为整型指针的引用
const 限定符
- 对const的引用
引用的类型必须和所引用的对象一致,但有例外:
初始化常量引用时允许使用任意表达式作为初始值,只要可以发生对应转换:非常量、字面值、表达式
- 要理解上述情况为什么可以发生:
在执行转换时生成一个临时的为命名对象,称为临时量,常量引用 引用的是这个临时量,由于常量引用的限制,无法进行修改,也就无须关注到两个其实是不同的对象; - 同时也可以认识到为什么非常量引用只能对应类型:
如果允许了转换,之后引用上的修改并不是原对象上的修改,也就失去了引用的意义,所以只能对应类型
double dval = 3.14;
double &d = dval;
const int &a = dval;
std::cout << a << std::endl;
std::cout << "&dval\t" << &dval << std::endl;
std::cout << "&d\t" << &d << std::endl;
std::cout << "&a\t" << &a << std::endl;
/* 输出
3 // 发生了转换
&dval 0x7ffc66b27880
&d 0x7ffc66b27880
&a 0x7ffc66b2787c // 确实不同
*/
const int i = 0;
int a = 1;
const int &ci = i; // 类型对应
const int &c1 = a; // 非常量
const int &c2 = 42; // 字面值
const int &c3 = c1 * 2; // 表达式
- 指针和const
指向常量的指针 const int *p;
指向对象层面的const,也称为底层const
常量指针 int *const p;
指针层面const,顶层const
- constexpr 和 常量表达式
[C++11]
常量表达式 指值不会改变,可在编译阶段确认结果的表示式
constexpr 类型的变量
constexpr int a = 5 + 1;
constexpr int b = a + 2;
constexpr类型的指针初始值只能为nullptr
,0
或具有固定地址对象的地址,如全局变量、静态变量,且constexpr int *p = 0;
定义的是一个常量指针,相当于int *const p;
处理类型
- auto类型说明符
[C++11]
auto 忽略顶层const
const int a = 1;
auto b = a; // b为int,顶层忽略
const int *const p = &a;
auto d = p; // d为const int *,底层保留,顶层忽略
const auto e = p; // 手动添加为 常量指针
- decltype类型指示符
返回操作数的数据类型,当作用于一个引用时返回的也是引用,而不是其原对象类型
int i = 0, *p = &i, &r = i;
decltype(r) a = i; // a: int& 必须初始化
decltype(r + 0) b = 0; // b: int
decltype(*p) c; // c: int& 未初始化error
decltype((i)) d; // d: int& 未初始化 有括号看作表达式返回引用
int i1 = 0, i2 = 1;
decltype(i1=i2) f = i1; // f: int& 赋值产生引用