目录
新增容器
编辑
新增语法
变量类型推导
auto
存储类型
分类
自动存储类型
静态存储类型
寄存器存储类型
外部链接存储类型
decltype
typeid(c++98)
type_info
{ }初始化
initializer_list
介绍
使用
模拟实现
为什么是值传参呢?
nullptr
final与override
范围for
框起来的都是c++11中新增的容器
存储类型
用来描述变量的存储、生命周期和作用域的属性
分类
自动存储类型,静态存储类型,寄存器存储类型和外部链接存储类型
自动存储类型
- 是局部变量的默认存储类别
- 这些变量在函数或块内部声明,它们的生命周期与包含它们的函数或块的执行周期相关联
- 当函数或块退出时,自动存储变量会被销毁
静态存储类型
- 在程序的生命周期内都存在,而不仅仅在其声明的作用域内
- 它们只被初始化一次
寄存器存储类型
- 用于请求编译器将变量存储在CPU的寄存器中,以加速对其的访问
- 关键字是register
- 但现代编译器通常会智能地管理寄存器,所以这个类型一般不再使用了
外部链接存储类型
- 这些变量可以在不同的文件中访问,它们通常被用于全局变量,以在不同的源文件之间共享数据
- 关键字是extern
但是 [局部域中定义局部的变量] 默认就是自动存储类型,所以auto就没啥用了
但c++11对auto进行了改变,让他可以根据初始化值的类型自动推导变量类型
注意:auto仅能通过初始值推导类型,而不能直接作为类型定义对象,所以传参/没有初始值的情况下,不能使用auto
decltype
delcltype的用处就体现了出来,auto不能做的,他可以做
他可以根据[decltype( 变量 )中变量的类型]作为一种类型,来声明/定义变量
int main() { const int x = 1; double y = 2.2; decltype(x * y) ret; // ret的类型是double decltype(&x) p; // p的类型是int* return 0; }
typeid(c++98)
- typeid是c++98引入的,但鉴于这里都是讲类型的,所以也介绍一下
- 它可以用来确定一个对象或表达式的实际运行时类型
- typeid返回一个type_info对象的引用,该对象包含有关表达式的类型信息
- 头文件:
也被称为统一初始化/列表初始化
原先,只有数组可以使用{ }进行初始化
但c++11进行了扩展,让所有的内置类型和自定义的类型都可以使用{ }进行初始化 :
int x = {42}; double y{3.14}; //加不加=都可以 int arr[] = {1, 2, 3, 4}; struct Point { int x; int y; }; Point p = {10, 20}; int* pa = new int[4]{ 0 }; //定义自定义对象,会调用其构造函数 Date d2{ 2022, 1, 2 }; Date d3 = { 2022, 1, 3 };
上面除了数组外,传入的都是[构造函数参数]个数的参数,也就是每次插入一个元素
而{ }初始化通过某个新类的支持,可以实现下面的操作(传入多个元素到容器中):
std::vector
vec = {1, 2, 3, 4}; 而这个新类就是下面要介绍的initializer_list
介绍
是 C++11 标准引入的一种容器,用于初始化容器类对象或用户自定义类型的对象
允许以初始化列表的形式传递多个值给对象的构造函数
使用
模拟实现
比如说,为之前模拟实现过的vector增加初始化列表的构造和赋值重载
/*myvector(const initializer_list
&l) //初始化列表构造(传入引用) : _start(nullptr), _finish(nullptr), _endOfStorage(nullptr) { cout << "深拷贝" << endl; reserve(l.size()); for (auto &it : l) { push_back(it); } }*/ myvector(initializer_list l) // 初始化列表构造 : _start(nullptr), _finish(nullptr), _endOfStorage(nullptr) { //cout << "深拷贝" << endl; reserve(l.size()); for (auto &it : l) { push_back(it); } } /*myvector &operator=(const initializer_list &l) // 初始化列表赋值(传入引用) { cout << "深拷贝" << endl; myvector tmp(l); swap(tmp); return *this; }*/ myvector &operator=(initializer_list l) // 初始化列表赋值 { cout << "深拷贝" << endl; myvector tmp(l); swap(tmp); return *this; } 可以是引用,也可以是传值
但我们会发现,库里的都是值传参
为什么是值传参呢?
一般我们使用的时候,都是这么写的:
myvector
s2 = {1, 2, 3, 4}; 这里会发生隐式类型转换,生成一个右值
- 如果直接写一个右值引用的参数,万一这个initializer_list是左值,就不方便了
- 所以可以写成const左值引用
- 但是可能会出现"悬挂引用"的问题(就是引用的对象已经销毁了)
- 所以,为了安全性,值传参是最好的选择
是 c++11 标准引入的关键字,用于表示空指针
这两个关键字实际上在多态那里已经介绍过了
范围for我们都快用烂了,非常好用的一个语法糖
底层就是调用了迭代器
除了这些之外,还有右值引用+移动语义,智能指针,lambda表达式,成员函数控制,可变参数模板,适配器,线程库,将在之后一一介绍