根据数据在容器中的排列特性,分为序列式(sequeence)和关联式(associative)
序列式容器:其中元素可序,但不一定有序,容器通过元素在容器中的位置顺序存储和访问元素
- C++本身提供了一个序列式容器:数组(array);
- STL中提供了vector,list,slist,deque,stack,queue,heap,priority-queue
- 其中stack和queue只是对deque进行了封装,所以被称为适配器
关联式容器:每个元素都有一个键值(key)和一个实值(value),通过键值存储和查找元素;
- 标准的关联式容器有set(集合)和map(映射表);以及根据set和map衍生出来的multiset和multimap;这些容器底层都是RB-Tree(红黑树)
- 另外STL还提供了非标准的hash table(散列表),以及以hash table 为底层机制实现的hash_set(散列集合),hash_map(散列映射表),hash_multiset(散列多键集合),hash_multimap(散列多键映射表)
set特性
...
template
class set {
//模板参数可以看出只有一个键值
...
typedef typename _Rep_type::const_iterator iterator;
//从源码中可以看到set的迭代器被定义为RB-Tree的const_iterator
//是一种constant iterator(mutable iterator)
multiset和set的唯一差别在于它允许键值重复,因此它的插入操作采用底层机制RB-Tree的insert_equal()
//部分源码
//从源码中可以看到调用的是insert_equal()
template <class _InputIterator>
multiset(_InputIterator __first, _InputIterator __last)
: _M_t(_Compare(), allocator_type())
{ _M_t.insert_equal(__first, __last); }//****
template <class _InputIterator>
multiset(_InputIterator __first, _InputIterator __last,
const _Compare& __comp,
const allocator_type& __a = allocator_type())
: _M_t(__comp, __a) { _M_t.insert_equal(__first, __last); }//****
#else
multiset(const value_type* __first, const value_type* __last)
: _M_t(_Compare(), allocator_type())
{ _M_t.insert_equal(__first, __last); }
multiset(const value_type* __first, const value_type* __last,
const _Compare& __comp,
const allocator_type& __a = allocator_type())
: _M_t(__comp, __a) { _M_t.insert_equal(__first, __last); }
multiset(const_iterator __first, const_iterator __last)
: _M_t(_Compare(), allocator_type())
{ _M_t.insert_equal(__first, __last); }
multiset(const_iterator __first, const_iterator __last,
const _Compare& __comp,
const allocator_type& __a = allocator_type())
: _M_t(__comp, __a) { _M_t.insert_equal(__first, __last); }
map特性
map的所有元素都是pair,同时拥有键值(key)和实值(value)
pair模板类用来绑定两个对象为一个新的对象,该类型在头文件中定义
template<class T1,class T2>
struct pair
{
typedef T1 first_type;
typedef T2 second_type;
T1 first;
T2 second;
pair()
:first(T1()),second(T2()){}
pair(const T1&a,const T2& b)
:first(a),second(b){}
};
...
template
class map {
//从模板参数可以看出键值和实值都存在
...
multimap和map的唯一差别在于它允许键值重复,所以调用的是底层机制RB-Tree的insert_equal()
//与map不同的地方
template <class _InputIterator>
multimap(_InputIterator __first, _InputIterator __last)
: _M_t(_Compare(), allocator_type())
{ _M_t.insert_equal(__first, __last); }
template <class _InputIterator>
multimap(_InputIterator __first, _InputIterator __last,
const _Compare& __comp,
const allocator_type& __a = allocator_type())
: _M_t(__comp, __a) { _M_t.insert_equal(__first, __last); }
#else
multimap(const value_type* __first, const value_type* __last)
: _M_t(_Compare(), allocator_type())
{ _M_t.insert_equal(__first, __last); }
multimap(const value_type* __first, const value_type* __last,
const _Compare& __comp,
const allocator_type& __a = allocator_type())
: _M_t(__comp, __a) { _M_t.insert_equal(__first, __last); }
multimap(const_iterator __first, const_iterator __last)
: _M_t(_Compare(), allocator_type())
{ _M_t.insert_equal(__first, __last); }
multimap(const_iterator __first, const_iterator __last,
const _Compare& __comp,
const allocator_type& __a = allocator_type())
: _M_t(__comp, __a) { _M_t.insert_equal(__first, __last); }
map的元素是“键-值”对的二元组形式:键用作元素在map中的索引,而值则表示所存储和读取的数据。set仅包含一个键,并有效地支持关于某个键是否存在的查询。set和map类型的对象所包含的元素都具有不同的键。如果需要一个键对应多个实例,则需要使用multimap或multiset类型。这两种类型允许多个元素拥有相同的键。