这几天大概了解了一下标准库里面的函数都是哪些方面的,然后去医院照顾奶奶了几天。期间看了容器和迭代器相关。
标准库的概述
大概有这么几种组件:字符串、正则表达式、IO流、智能指针、异常、数学工具、时间工具、随机数、初始化列表、pair和tuple、optional、variant和any、函数对象、文件系统、多线程、类型特质、标准整数类型、容器、算法。
但同时标准库还有一些不支持的内容:多线程访问容器不能保证线程安全、没有提供泛型的树、图结构。
但是可以编写兼容标准库的代码,来扩展它。
容器和迭代器
容器是泛型数据结构,适合保存数据集合。(不用再像去年那样手写链表了)。除了array和bitset外,大部分标准库容器的大小灵活可变。
16种容器,四大类:
- 顺序容器:
- vector(动态数组)
- deque
- list
- forward_list
- array
- 关联容器:
- map
- multimap
- set
- multiset
- 无序关联容器或哈希表:
- unordered_map
- unordered_multimap
- unordered_set
- unordered_multiset
- 容器适配器:
- queue
- priority_queue
- stack
对元素的要求
标准库容器对元素使用值语义(value semantic)。也就是,在输入元素时保存元素的一份副本。通过赋值运算符给元素赋值,通过析构函数销毁元素。所以,在编写适用于标准库的类时,一定要保证它们是可以复制的。请求容器中的元素时,会返回所存副本的引用。
如果喜欢引用语义,可以存储元素的指针,而非元素本身。当容器复制指针时,仍然指向同一元素。另一种方式是在容器中存储std::reference_wrapper。可使用std::ref()或std::cref()来创建reference_wrapper,使引用变得可以复制。其相关函数和类模板在functional头文件中。
容器中,可能存储“仅移动”类型。这是非可复制类型,这样做是,编译器可能报错。std::unique_ptr是仅移动的例子。
在容器内保存指针应该使用unique_ptr或shared_ptr。
标准库容器的一个模板类型参数是分配器(allocator)。标准库容器可使用分配器为元素分配或释放内存。分配器类型参数具有默认值,因此几乎总是可以忽略它。
有一些容器(如map)也可将比较器(comparator)作为模板类型参数。比较器用于排序元素,具有默认值,一般不需要指定。
实现元素的移动语义可以提高性能(要标记noexcept)
异常和错误检查
标准库容器提供了非常有限的错误检查功能。客户应确保使用正确。
迭代器
标准库通过迭代器模式提供了访问容器元素的泛型抽象。每个容器都提供了容器特定的迭代器,迭代器实际上是增强版的智能指针,这种指针知道如何遍历特定容器的元素。所有不同容器的迭代器都遵循C++标准中定义的特定接口。因此, 即使容器提供不同的功能,访问容器元素的代码也可以使用迭代器的统一接口。
所有迭代器都必须可通过复制来构建、赋值、并且可以析构。左值可以交换。C++标准提供了5大迭代器:
输入迭代器
operator++,operator*,operator->,复制构造函数,operator=,operator==,operator!=。
提供只读访问,只能前向访问(没有operator--提供的后向访问功能)。这个迭代器可以赋值和复制,可以比较判等。
输出迭代器(“写”迭代器)
operator++,operator*,复制构造函数,operator=
提供只写访问,只能前向访问。这个迭代器只能赋值,不能判等比较。
输出迭代器特有操作*iter = value
(此类迭代器缺少operator->,但提供前缀和后缀operator++)
前向迭代器
输入迭代器的功能,加上默认构造函数。
提供读写访问,只能前向访问。可以赋值、复制、比较判等。
双向迭代器
前向迭代器的功能+operator--
提供前缀和后缀operator--
随机访问迭代器
双向迭代器的功能+ operator+ ,-,+=,-+,<,>,<=,>=,[]
等同于普通指针;此类迭代器支持指针运算、数组索引语法以及所有形式的比较。
同时,满足输出迭代器要求的迭代器称为“可变迭代器”,否则不变迭代器。
可以用std::distance来计算容器的两个迭代器之间的距离。
(迭代器类似于智能指针,因为他们都重载了特定的运算符)