STL学习笔记--序列式容器
1、vector
vector是一个线性顺序结构。相当于数组,但其大小可以不预先指定,并且自动扩展。故可以将vector看作动态数组。
在创建一个vector后,它会自动在内存中分配一块连续的内存空间进行数组存储,初始的空间大小可以预先指定也可以由vector默认指定,这个大小即capacity()
函数的返回值,当存储的数据超过分配的空间时,vector会重新分配一块内存。
重新分配内存的动作:
(1)申请一块更大的内存
(2)将原来的数据复制到新的内存块中
(3)销毁掉原内存块中的对象
(4)释放原来的内存空间
但重新分配内存是很耗时的,会导致糟糕的性能,而且一旦内存重新分配,和vector元素相关的references,pointers,iterators都会失效。
所以vector性能优异的秘诀是:配置比其所容纳的元素更多的内存。
1)使用reserve()
保留适当容量,避免一再重新配置内存。
2)如果预先知道vector可能容纳元素的多少,在创建vector时就指定其空间大小。
//使用reserve申请适当的内存,仅分配内存,size()的大小不变
vector<int> v; //create an empty vector
v.reserve(80);// reserve memory for 80 elements
//在创建vector时指定空间大小,这种方式要调用构造方法,如果只是为了保留足够的内存
//建议使用上面的reserve方法
//create a vector and call 80 times the default constructor
vector<int> v(80);
vector的特点:
(1)元素连续存储,空间可以动态扩展。
(2)可以随机访问,像数组一样被访问,即支持[]操作符和vector.at()。
(3)在末端增加和删除元素性能较好,在内部进行插入、删除操作效率非常低。
(4)vevtor的迭代器是随机存储迭代器,可以操作所有的STL算法。
(5)只能在vector的最后进行push pop操作。
vector的一些使用技巧:
(1)vector的clear()
方法并不会释放vector所申请的内存,只是清除了存储在vector中的元素,capacity的大小并不会变。
const int MAX_NUM = 1000;
vector<int> v;
for (int i = 0; i < MAX_NUM; i++)
{
v.push_back(i);
}
cout << "Before Clear:\n";
cout << "size:" << v.size() << endl;
cout << "capacity:" << v.capacity() << endl;
v.clear(); //并不会释放vector占用的内存,即capacity的大小不变
//v.swap(vector<int>());
cout << "After Clear:\n";
cout << "size:" << v.size() << endl;
cout << "capacity:" << v.capacity() << endl;
要想彻底释放vector占用的内存,可以采用swap方法实现:
v.swap(vector<int>());
采用swap后的效果:
(2)缩减vector的容量到合适(shrink to fit)。
有时候经过一系列的操作,vector的元素个数终将稳定,但可能vector的容量还是很大,为了节约内存,可采取下面的操作使vector的容量缩减至合适。
两个vector交换内容后,两者的容量也会交换,下面的例子虽然保留了元素,却缩减了容量。
const int MAX_NUM = 1000;
vector<int> v;
for (int i = 0; i < MAX_NUM; i++)
{
v.push_back(i);
}
cout << "Before Clear:\n";
cout << "size:" << v.size() << endl;
cout << "capacity:" << v.capacity() << endl;
//
vector<int>::iterator iter = std::find(v.begin(),v.end(),100);
if (iter != v.end())
{
v.erase(iter,v.end());
}
cout << "\nAfter a series of operators:\n";
cout << "size:" << v.size() << endl;
cout << "capacity:" << v.capacity() << endl;
//shrink to fit 缩减容量
vector<int>(v).swap(v);
cout << "\nAfter shrink to fit:\n";
cout << "size:" << v.size() << endl;
cout << "capacity:" << v.capacity() << endl;
2、deque
deque也采用动态数组来管理元素,提供随机存储。和vector不同的是,deque的动态数组头尾都开放,能做在头尾两端进行快速安插和删除。
deque采用多个连续的存储块,并且在一个映射结构中保存对这些块及其顺序的追踪。
deque的特点:
(1) 两端都能快速安插元素和移除元素(vector只能在尾端)
deque<int> d;
const int _MAX = 6;
for (int val = 0; val < _MAX; val++)
{
d.push_back(val);
d.push_front(val);
}
std::copy(d.begin(), d.end(),std::ostream_iterator<int>(cout," "));
(2) deque不支持对容量和内存重分配时机的控制。无capacity
及reserve
操作。deque的内存重分配优于vector,不必在内存重分配时复制所有的元素。
(3) 和vector一样在中间部分安插、移除元素的速度相对较慢。
3、list
list使用一个doublely linked list(双向链表)来管理元素。它的数据由若干个节点构成,每一个节点都包含一个信息块(实际数据)、一个前驱指针和一个后驱指针。list使用的是非连续的内存空间。
list与vector、deque的区别:
(1) list不支持随机存取。由于内部结构的原因,list的随机检索性能低下,检索时间与目标元素位置成正比。
(2) 任何位置(不只是两端)执行元素的安插和移除都非常快,始终是常数时间内完成。
(3) 安插与删除并不会造成指向其它元素的各个pointers、references、iterators失效。
(4) list未提供容量、空间重新分配等操作,因为没有必要,每个元素都有自己的内存,在被删除之前一直有效。
(5) list提供了不少特殊的成员函数,专门用于移动元素。较之同名的STL通用算法,效率更高。
如: sort()
remove()
remove_if()
//list的移除操作和排序
cout << "list test:\n";
list<int> list1;
for (int val = 1; val < 5; val++)
{
list1.push_back(val);
list1.push_front(val);
}
std::copy(list1.begin(), list1.end(),std::ostream_iterator<int>(cout," "));
int remove_element = 4;
cout << "\nRemove [" << remove_element <<"]:" << endl;
list1.remove(remove_element); //移除元素4
std::copy(list1.begin(), list1.end(),std::ostream_iterator<int>(cout," "));
cout << "\nSort:" << endl;
list1.sort(std::greater<int>()); //降序排列
std::copy(list1.begin(), list1.end(),std::ostream_iterator<int>(cout," "));
//vector的移除元素和排序操作
cout << "\nvector test:\n";
vector<int> v;
for (int val = 1; val < 5; val++)
{
v.push_back(val);
v.push_back(val + 1);
}
std::copy(v.begin(), v.end(),std::ostream_iterator<int>(cout," "));
//移除元素 1
int ele = 1;
cout << "\nAfter Remove [" << ele <<"]:\n";
v.erase(std::remove(v.begin(),v.end(),ele),v.end());//删除元素操作
std::copy(v.begin(), v.end(),std::ostream_iterator<int>(cout," "));
//排序
cout << "\nSort:\n";
std::sort(v.begin(),v.end(),std::greater<int>()); //降序排列
std::copy(v.begin(), v.end(),std::ostream_iterator<int>(cout," "));
4、vector,deque,list三者比较
vector是一段连续的内存块,而deque是多个连续的内存块, list是所有元素分开保存。
vector的查询性能最好,并且在末端增加数据也很高效,除非它重新分配内存。vector适合高效的随机存储。
list是一链表,任何一个元素都可以是不连续的,它有一个前驱指针和一个后驱指针。所以list对元素的插入、删除的性能最好。list适合大量地插入和删除操作而不关心随机存储的需求。
deque介于两者之间,是对vector和list优缺点的结合,是处于两者之间的一种容器。如果需要随机存取又关心两端数据的插入和删除,deque是最佳之选。
STL学习笔记--序列式容器的更多相关文章
- STL学习笔记--关联式容器
关联式容器依据特定的排序准则,自动为其元素排序.缺省情况下以operator<进行比较.set multiset map multimap是一种非线性的树结构,具体的说是采用一种比较高效的特殊平 ...
- 侯捷STL学习(九)--关联式容器(Rb_tree,set,map)
layout: post title: 侯捷STL学习(九) date: 2017-07-21 tag: 侯捷STL --- 第十九节 容器rb_tree Red-Black tree是自平衡二叉搜索 ...
- STL源码--序列式容器
1. vector: vector的内存管理,动态分配内存,不需要程序员来维护存储空间,是与array最大的区别,程序员只需从逻辑上关注代码,而不需要对内部的存储空间的分配和回收分心.首先,vecto ...
- STL学习笔记(三) 关联容器
条款19:理解相等(equality)和等价(equivalence)的区别 相等的概念是基于 operator== 的,如果 operator== 的实现不正确,会导致并不实际相等等价关系是以&qu ...
- STL学习笔记(序列式容器)
Vector Vector是一个动态数组. 1.Vector的操作函数 构造.拷贝和析构 vector<Elem> c //产生一个空vector ,其中没有任何元素 vector< ...
- STL源码剖析读书笔记--第四章--序列式容器
1.什么是序列式容器?什么是关联式容器? 书上给出的解释是,序列式容器中的元素是可序的(可理解为可以按序索引,不管这个索引是像数组一样的随机索引,还是像链表一样的顺序索引),但是元素值在索引顺序的方向 ...
- STL序列式容器学习总结
STL序列式容器学习总结 参考资料:<STL源码剖析> 参考网址: Vector: http://www.cnblogs.com/zhonghuasong/p/5975979.html L ...
- STL源码剖析之序列式容器
最近由于找工作需要,准备深入学习一下STL源码,我看的是侯捷所著的<STL源码剖析>.之所以看这本书主要是由于我过去曾经接触过一些台湾人,我一直觉得台湾人非常不错(这里不涉及任何政治,仅限 ...
- STL源码剖析——序列式容器#1 Vector
在学完了Allocator.Iterator和Traits编程之后,我们终于可以进入STL的容器内部一探究竟了.STL的容器分为序列式容器和关联式容器,何为序列式容器呢?就是容器内的元素是可序的,但未 ...
随机推荐
- 5、Cocos2dx 3.0游戏开发找小三之測试例子简单介绍及小结
重开发人员的劳动成果.转载的时候请务必注明出处:http://blog.csdn.net/haomengzhu/article/details/27186557 測试例子简单介绍 Cocos2d-x ...
- Nginx(一)-- 初体验
1.概念 Nginx ("engine x") 是一个高性能的 HTTP 和反向代理服务器,也是一个 IMAP/POP3/SMTP 服务器. Nginx提供基本http服务,可以作 ...
- mac 安装mysql 修改密码
我草!!! 上网查资料,安装mysql,一大推废话,简直就是他妈的瞎扯淡,真是能他妈的瞎编,草! 为了不让后面的同学看到那些狗屁不通的资料,我把自己安装mysql的步骤,以及修改mysql密码的方法梳 ...
- console.log篇
前言: 从接触变成开始,就用到了神奇的“console.log”,原来其中还有很多不为自己知道的“小秘密”,今天就深入研究一下吧 1.可以F12打开控制台,输入console.log(xxx),就可以 ...
- 浅谈MVC和MVVM模式
MVC I’m dating with a model… and a view, and a controller. 众所周知,MVC 是开发客户端最经典的设计模式,iOS 开发也不例外,但是 MVC ...
- <转>Logistic回归总结
转自http://blog.csdn.net/dongtingzhizi/article/details/15962797 当我第一遍看完台大的机器学习的视频的时候,我以为我理解了逻辑回归,可后来越看 ...
- poj_3185 反转问题
题目大意 有20个碗排成一排,有些碗口朝上,有些碗口朝下.每次可以反转其中的一个碗,但是在反转该碗时,该碗左右两边的碗也跟着被反转(如果该碗为边界上的碗,则只有一侧的碗被反转).求最少需要反转几次,可 ...
- 【PHP】php 生成条形码
1.什么是条形码? 百度百科定义:条形码(barcode)是将宽度不等的多个黑条和空白,按照一定的编码规则排列,用以表达一组信息的图形标识符.常见的条形码是由反射率相差很大的黑条(简称条)和白条(简称 ...
- dialog里面数据更新问题
在实际开发中经常会用到showDialog(int id)的方法来展示一个对话框,但是会遇到一个Dialog展示之后下次再show的时候对话框的界面还是上次展示的那个,而不是我们想象的界面.很多时候我 ...
- MQTT的学习研究(十六) MQTT的Mosquitto的window安装部署
在mqtt的官方网站,有许多mqtt,其中:MosquittoAn Open Source MQTT server with C, C++, Python and Javascript clients ...