容器:用来管理某类对象的结合
迭代器:用来遍历容器的元素
算法:用来处理容器的元素
基本容器分类
1、序列式容器
序列式容器是一种有序容器。这里的有序不是指容器里的元素一定是按从小到大或从大到小等排列规则排序好;而是指元素插入容器后,若不人为改动元素间的相对位置,那它的位置就不会改变。STL提供了5中序列式容器:array、vector、deque、list 和forward_list,内部存储结构一般为array或linked list。
vector
vector相当于一个动态数组,其内部存储结构就是动态数组。所以它具备数组的优缺点:
支持随机访问。
尾部可快速插入、删除元素。
头部或中间插入、删除操作需要移动元素,比较费时。
deque
deque也是一种数组,和vector不同的是,deque还支持头部快速插入、删除数据,其内部存储结构是分段数组。
array
array相当于静态数组,也就是大小固定的数组。
list
list的内部存储结构是双向链表,不提供随机访问,但因为可快速获取前导、后继元素,所以可快速在任意位置插入、删除元素。
forward_list
forward_list是一个单向链表,是一个受限的list,每个元素只提供了后继指针。
2、关联式容器
关联式容器是一种自动排序集合,元素位置取决于value(如果元素是key/value则取决于key)以及排序规则。默认排序规则是operator <,所以使用关联式容器的对象,需要实现operator < 或者提供特定的排序规则。关联式容器可以在对数时间复杂度内查找元素,但不能直接改动元素的值,因为会破坏元素的自动排序。STL提供了4种关联式容器:set、multiset、map和multimap,内部实现一般为binary tree。
set
元素为单值value,依据value自动排序,元素不允许重复。
multiset
相对于set,multiset允许重复元素。
map
元素key/value,依据key进行自动排序,元素中key不允许重复。
multimap
相对于map,multimap允许可以元素中key重复出现。
3、无序容器
无序容器时一种无序集合,它关注的是元素是否在集合中。STL提供了4中无序容器:unordered_set、unordered_multiset、unorder_map和unorderde_multimap,内部实现一般为hash table。
容器适配器
这些容器利用基本容器实现,包括:stack、queue、priority queue
迭代器
迭代器内部实现是智能指针,能够遍历各种容器。但各种容器内部的数据结构不一样,需要不一样的遍历逻辑。所以每种容器都以嵌套类的形式提供了各自的迭代器实现。
基本操作:
operator *:访问当前位置的元素
operator ->:访问当前位置元素的成员
operator ++:迭代器前进至下一个元素
operator == 和 operator ~=:判断迭代器是否指向同一个位置
operator =:迭代器赋值
为了支持迭代器的运作,容器类也需要提供一些基本成员函数:
begin():返回一个指向容器起点的迭代器,也就是指向第一个元素的位置。
end():返回一个指向容器终点的迭代器,终点是指最后一个元素的下一个位置。
begin() 和 end() 返回的是 iterator读写功能,C++ 11开始提供的 cbegin() 和 cend() 返回const_iterator对象,只支持读功能。
并不是说C++ 11之前不能使用只有读功能的迭代器,const_iterator在C++ 11之前就存在:
vector<int> vec{1,2,3,4,5};
for (vector<int>::const_iterator iter = vec.begin(); iter != vec.end(); iter++)
{
std::cout << *iter << std::endl;
}
C++11新增的auto关键字可以使上面的代码更简洁,但是会牺牲了const属性,于是就需要搭配 cbegin() 和 cend()使用
vector<int> vec{1,2,3,4,5};
for (auto iter = vec.cbegin(); iter != vec.cend(); iter++)
{
std::cout << *iter << std::endl;
}
每种容器都提供了 iterator 和 const_iterator,但是前面提到每个容器是以嵌套类来实现各自的迭代器,所以它们支持的操作也是不尽相同:
1、前向迭代器,只支持 operator++ 递增操作,forward_list的迭代器是前向迭代器。
2、双向迭代器,支持 operator++ 递增和 operator-- 递减操作,list、set、multiset、map 和 multimap 提供双向迭代器。
3、随机访问迭代器,除递增、递减操作外,还提供增减一个偏移量、计算两迭代器距离、operator> 和 operator< 等操作,vector、deque、array 和 string 提供随机访问迭代器。
此外,标准库还提供了输入迭代器和输出迭代器。
迭代器适配器
迭代器适配器也是迭代器,是在基础迭代器基础上实现的具有特殊功能的迭代器。包括反向迭代器、插入迭代器、流迭代器和移动迭代器。具体内容在《迭代器适配器》中介绍。
算法
算法是一系列操作容器内元素的全局函数,没有实现为容器类的成员函数,搭配迭代器可以应用于所有容器,这是一种泛型函数编程思想。
算法都是搭配迭代器使用,迭代器指示了算法的操作区间,区间都按半开区间(包括起始元素位置,不包括末尾元素位置)解释。
部分算法对多个区间进行操作,一般只需要提供第一个区间的起点和终点,其它区间只需要提供起点,终点则根据第一个区间推导出来。