1.容器(Container)主要包括:
序列式(Sequence containers):
Vector(其实就是个数组,只不过预留了部分空间)
将元素置于一个动态数组中加以管理,可以随机存取元素(用索引直接存取),数组尾部添加或移除元素非常快速。但是在中部或头部安插元素比较费时;
List(其实是个双向链表)
不提供随机存取(按顺序走到需存取的元素,O(n)),在任何位置上执行插入或删除动作都非常迅速,内部只需调整一下指针;
Deque(双端队列,其实内部存储是通过迭代器把n个固定空间的数组连接在一起的,实现了相当于双端队列的功能)
是double-ended queue的缩写,可以随机存取元素(用索引直接存取),数组头部和尾部添加或移除元素都非常快速。但是在中部或头部安插元素比较费时
关联式(Associated containers):
有序:(其实内部通过红黑树实现,所以有序)
Map/Multimap : Map的元素是成对的键值/实值,内部的元素依据其值自动排序,Map内的相同数值的元素只能出现一次,Multimaps内可包含多个数值相同的元素,内部由红黑树实现,便于查找;
Set/Multiset: 内部的元素依据其值自动排序,Set内的相同数值的元素只能出现一次,Multisets内可包含多个数值相同的元素,内部由红黑树实现,便于查找;对于set来说本身就是键值
无序:(其实内部通过哈希表hash table实现,所以无序)
unordered_map
Map的元素是成对的键值/实值,Map内的相同数值的元素只能出现一次,Multimaps内可包含多个数值相同的元素,
unordered_multimap
unordered_set
Set内的相同数值的元素只能出现一次,Multisets内可包含多个数值相同的元素
unordered_multiset
2.容器适配器(Adaptor)主要包括:
感觉这个算是容器的容器,因为其他容器都有独立封装,而适配器的底层其实是对这些容器的再次封装,所以没有归类为容器
queue(FIFO队列):再次封装了deque容器,阉割或者说是限制了两端进出和随机存取的功能
stack(栈):再次封装了deque容器,阉割或者说是限制了两端进出和随机存取的功能
priority_queue(优先级队列):逻辑上主要是利用了堆排序,底层上封装的是vector
序列式容器迭代器失效问题
对于序列式容器,例如vector、deque;由于序列式容器是组合式容器,当当前元素的iterator被删除后,其后的所有元素的迭代器都会失效,这是因为vector,deque都是连续存储的一段空间,所以当对其进行erase操作时,其后的每一个元素都会向前移一个位置。
vector迭代器失效问题总结
(1)当执行erase方法时,指向删除节点的迭代器全部失效,指向删除节点之后的全部迭代器也失效
(2)当进行push_back()方法时,end操作返回的迭代器肯定失效。
(3)当插入(push_back)一个元素后,capacity返回值与没有插入元素之前相比有改变,则需要重新加载整个容器,此时first和end操作返回的迭代器都会失效。
(4)当插入(push_back)一个元素后,如果空间未重新分配,指向插入位置之前的元素的迭代器仍然有效,但指向插入位置之后元素的迭代器全部失效。如果重新分配空间,那么全部失效。
deque迭代器失效总结:
(1)对于deque,插入到除首尾位置之外的任何位置都会导致迭代器、指针和引用都会失效,但是如果在首尾位置添加元素,迭代器会失效,但是指针和引用不会失效
(2)如果在首尾之外的任何位置删除元素,那么指向被删除元素外其他元素的迭代器全部失效
(3)在其首部或尾部删除元素则只会使指向被删除元素的迭代器失效。
如何解决 ?当使用erase()时,将返回一个指向下一个地址的迭代器,因此我们需要注意判断迭代器+1的情况。
例如:it=str.erase(it);此时的迭代器it就指向了删除元素的下一个元素