stl有以下几种容器 vector deque list set map
vector
vector其实就是一个数组,是一个连续空间。所以他支持快速的随机访问,直接基质+偏移就可以找到目标。
vector的容量并不是使用多少就开辟多少,每次不够用的时候,会多开辟一点,规则是简单2,可见下面的示例代码,如果使用Reserve之后还不够,就会在Reserve的基础上2。
因此,也同时带来一个缺点,那就是迭代器失效,由于不够用的时候,空间是重新开辟的,所以原来的地址就无效了,此外,vector会进行一次内存拷贝,如果量大的话,容易出现性能问题。所以一般在使用大量数据的时候,会先使用Reserve确定一个最大容量,避免后续分配不足导致的重新开辟。
vector<int> test;
for(int i = 0; i< 10; i++)
{
test.push_back(0);
printf("addrs: %p, cap: %d\n", &test[0], test.capacity());
}
addrs: 0x22ee060, cap: 1
addrs: 0x22ee080, cap: 2
addrs: 0x22ee060, cap: 4
addrs: 0x22ee060, cap: 4
addrs: 0x22ee0a0, cap: 8
addrs: 0x22ee0a0, cap: 8
addrs: 0x22ee0a0, cap: 8
addrs: 0x22ee0a0, cap: 8
addrs: 0x22ee0d0, cap: 16
addrs: 0x22ee0d0, cap: 16
dqueue
dqueue是基于双端链表 ,可以从头部和尾部插入。
他的内存分布相对连续,即初始时预分配一块连续空间,当不够用了的时候,会继续分配新的空间挂到原链表尾部。相比于vector,dqueue不会拷贝旧内存。
dqueue支持随机访问,效率等同于vector。
list
list的底层实现是一个双向链表,内存分布是离散的。
所以,list不支持随机访问(因为需要遍历,效率很差),但是对于制定节点的插入和删除是非常高效的,不涉及内存拷贝。
相比于set,list没有key的概念,无排序。
set
set底层是一个rbtree。纯key的数据结构,也即key就是value。
所以,set有以下几个特点。
1 插入删除高效
2 容器内数值不重复(因为是key),常用来去重或者标识是否存在。
3 具备自动排序。
set<int> test;
test.insert(3);
test.insert(2);
test.insert(1);
test.insert(2);
for(auto it = test.begin(); it != test.end(); it++)
{
cout<<*it<<endl;
}
1
2
3
无需排序的场合,也可以使用hash_set,底层实现是一个hashtable,散列式存储,无排序,插入删除效率相比于set更为高效。
map
底层实现基本等同于set,按照key排序,区别是map多存储了value。
如果需要无排序的map可以使用unordered_map,基于hash_table实现。