目录
一. 列表初始化
- 在 C 语言中, 就可以使用 {} 对数组或结构体进行初始化, 而 C++11 扩大了 {} 的使用范围, 使其可以初始化所有的内置类型和自定义类型, 并且使用时可以省略 =.
int main()
{
// 可以使用 {} 给所有类型初始化, 并且可以省略 赋值符号
int arr1[]{ 1,2,3 };
int a1 = { 1 };
int a2{ 2 };
int* p1 = { &a1 };
int* p2{ nullptr };
int* p3 = new int{3};
vector<int> v1 = { 1 };
vector<int> v2{ 1,2 };
return 0;
}
1. 列表初始化的原理: initializer_list
- initializer_list 是 C++11 新添加的一个类, 支持迭代器. initializer_list - C++ Reference
当使用初始化列表时, initializer_list 会自动将一个由相同元素构成的列表转化为一个 initializer_list 的对象;
但需要注意的是, initializer_list 对象中的元素实际是常量值, 是无法改变 initializer_list 对象中元素的值.
- 在 C++11 允许构造函数和其他函数把初始化列表当做参数.
- 当使用列表初始化时, 若列表初始化中的参数与类的构造函数相匹配, 那么就会直接调用构造函数;
若不匹配或列表赋值时, 则会创建 initializer_list 的对象, 调用参数为 initializer_list 的构造或赋值函数.
int main()
{
//直接调用构造函数
string s1{"123"};
//调用参数为 initializer_list 的构造函数
vector<int> v1{ 1,2 };
//调用参数为 initializer_list 的赋值函数
v1 = { 1,2,3 };
return 0;
}
二. 类型的声明
1. auto
- 在 C++98 中 auto 是一个存储类型的说明符, 表明变量是局部自动存储类型, 但在局部域中定义的局部变量默认就是自动存储类型, 所以auto就没什么大用;
在 C++11 中改变 auto 的用法, 将其实现自动类型推导. 不过必须对 auto 定义的变量进行显示初始化, 这样编译器才能将定义对象的类型设置为初始化值的类型.
2. decltype
- decltype 可以获取参数的类型, 将变量的类型声明为表达式指定的类型;
- 类似 typeid().name(), 不过 decltype 获取的是真正的类型, 可以当作类型声明使用, 而 typeid().name() 获取的只是字符串.
与 auto 相比:
decltype 需要参数;
decltype 无需显式实例化, 可以直接定义;
decltype 可以作为模板参数传递.
三. nullptr
由于 C++11 之前空指针 NULL 被定义成字面量 0, 在传参等情况会导致二义性, 所以在 C++11 中新增了关键字 nullptr, 用于表示空指针.
#ifndef NULL
#ifdef __cplusplus
#define NULL 0
#else
#define NULL ((void *)0)
#endif
#endif
四. 范围 for
范围 for 的功能就是遍历容器并取出所有的元素;
而底层使用的就是迭代器, 所以支持迭代器的容器就会支持范围 for.
//此处的 it 类型为迭代器的类型
for (auto it = begin(); it != end(); it++)
{
// 对迭代器进行操作
}
//此处的 e 类型为容器元素的类型
//若希望减少拷贝或修改容器元素, 可以使用引用类型, (auto& e : 容器)
for (auto e : 容器)
{
// 对 e 进行操作(e 为容器元素的拷贝)
}
五. STL容器变化
- 新增容器
C++11 为 STL 增加了几种新容器, unordered_map/unordered_set 都是使用哈希思想实现的容器, 底层为散列表.
- 新增接口
initializer_list 系列的接口;
右值引用的相关接口;
新增了 const 迭代器的接口.
六. 类的新功能
C++11 类的主要增加了以下新功能:
默认成员函数增加了移动构造和移动赋值;
允许类的成员变量使用缺省值进行初始化;
增加强制生成和强制禁止生成默认函数的关键字 default 和 delete;
继承和多态部分增加 final 和 override 关键字.