stl——vector详解
stl——vector详解
stl——vector是应用最广泛的一种容器,类似于array,都将数据存储于连续空间中,支持随机访问。相对于array,vector对空间应用十分方便、高效,迭代器使vector更加灵活、安全。设计皆由vector起,键盘之下尽vector。
1 vector本质
vector数据结构如下,通过三个迭代器start, finish, end_of_storage的系列public接口,可很好地完成数据存储、溢出判断(iter >= iv.end())、大小、容量(容量与大小不等,以免不断申请空间耗费资源)、重载操作符[]、判空、最前元素、最后元素等等。
class vector{
…
protected:
iterator start ;
iterator finish;
iterator end_of_storage;
public:
iterator begin () { return start ; }
iterator end() { return finish; }
size_type size() const { return size_type( end() - begin()); }
size_type capacity() const { return size_type(end_of_storage - begin()); }
bool empty () const { return begin() == end(); }
reference operator[] (size_type n) { return *(begin() + n); }
reference front () { return *begin(); }
…
}
由于vector是用连续空间存储数据,不断扩容将导致大量的新空间申请、元素拷贝和释放原有空间,十分耗时,vector申请空间时,都将多申请部分空间备用,如下图的[finish, end_of_storage)所示。只有当finish == end_of_storage时,再申请新的空间(2*capacity()), 图2就是在图1的基础上,再插入元素引起的空间变化时的数据存储情景。
图1 vector数据存储-1
在图1和图2中的start不再指向相同的地址,扩大空间是新请新的更大的空间,因而不仅是start迭代器,其它指向空间变化前vector的迭代器都将失效。此处极易引起bug。
图2 vector数据存储-2
2 vector常用方法与技巧
1、空间申请
构造函数、reserve()、resize()。
1: vector<int> iv(3, -1);
2: iv.reserve(10);
3: iv.resize(10, -1);
构造函数不述;
reserve(n),申请空间,等同于扩大[finish, end_of_storage),当n <= capacity()时,无效,可以理解为主要改变end_of_storage(或capacity)——reserve()匹配capacity();
resize(10),申请空间并赋值,等同于改变[start, finish),可以理解为主要改变finish(或size())——resize()匹配size()。
2、空间释放
erase()、resize()、clear()均仅改变finish(或size()),不改变end_of_storage。
swap()释放空间——清空,改变end_of_storage:
vector<int> iv(10, -1);
iv.reserve(500);
vector<int>().swap(iv);//交换空间
cout<<iv.capacity()<<endl;//输出0
swap()释放空间——释放多余空间,改变end_of_storage:
vector<int> iv(10, -1);
iv.reserve(500);
vector<int>(iv).swap(iv);//交换空间
cout<<iv.capacity()<<endl;//输出10
3、resize()与operator []
operator []使得vector与array处理完全类似,但operator []极易引起异常与错误,如下:
vector<int> iv();
iv.reserve(500);
iv[300] = -1;
cout<<iv.capacity()<<endl;//输出500
cout<<iv.size()<<endl;//输出0
这里就引起了迭代器不符合预期,也不知道什么才是预期。建议用法为resize()与operator []一起使用,从而使得操作完全等同于array,且安全:
vector<int> iv();
iv.resize(500, 0);
iv[300] = -1;
cout<<iv.capacity()<<endl;//输出500
cout<<iv.size()<<endl;//输出500
4、vector迭代器
vector的迭代器十分简单,等同于指针,++、--、+n、-n、>、<、!=等操作都可应用——random access iterator,基本上全部stl algorithms均可以在此上应用。
PS:强烈不推荐使用>,<,≤,≥之类比较迭代器,遍历时直接使用!=即可,以免混于其它非random access iterator的容器。
参考资料:
1、侯捷. STL源码剖析;
2、侯捷. STL源码剖析注释;
对于同仁们的布道授业,一并感谢。
----
stl——vector详解的更多相关文章
- C++STL vector详解(杂谈)
介绍 这篇文章的目的是为了介绍std::vector,如何恰当地使用它们的成员函数等操作.本文中还讨论了条件函数和函数指针在迭代算法中使用,如在remove_if()和for_each()中的使用.通 ...
- C++ STL vector详解
一.解释: vector(向量):是一种顺序容器,事实上和数组差不多,但它比数组更优越.一般来说数组不能动态拓展,因此在程序运行的时候不是浪费内存,就是造成越界.而vector正好弥补了这个缺陷,它 ...
- C++ STL之vector详解
转自http://blog.sina.com.cn/s/blog_9f1c0931010180cy.html Vectors vector是C++标准模板库中的部分内容,它是一个多功能的,能够操作 ...
- STL之vector详解
一.vector容器的自增长 首先,我们知道vector容器是由数组做出来的:它具备了数组的优缺点. 数组的优点: 操作数据,读取速度很快,因为有下标: 数组的缺点: 分配之后不能在改变大小: #in ...
- STL deque详解
英文原文:http://www.codeproject.com/Articles/5425/An-In-Depth-Study-of-the-STL-Deque-Container 绪言 这篇文章深入 ...
- c++ vector详解
容器有太多需要清楚细节的地方,同时也有太多值得学习的地方.下文作为学习.工作中用到vector的总结. 1. 赋值运算=的实现原理 在使用赋值操作时,如果不清楚内部是怎么实现,那么用起来会畏手畏脚. ...
- C++ STL map详解
一.解释: p { margin-bottom: 0.25cm; direction: ltr; color: #00000a; line-height: 120%; text-align: just ...
- C++ STL 优先队列详解
一.解释: 优先队列是队列的一种,不过它可以按照自定义的一种方式(数据的优先级)来对队列中的数据进行动态的排序,每次的push和pop操作,队列都会动态的调整,以达到我们预期的方式来存储. 例如,将元 ...
- 关联容器map(红黑树,key/value),以及所有的STL容器详解
字符串或串(String)是由数字.字母.下划线组成的一串字符.一般记为 s=“a1a2···an”(n>=0).它是编程语言中表示文本的数据类型.在程序设计中,字符串(string)为符号或数 ...
随机推荐
- 开发现代ASP.NET应用程序
新思想.新技术.新架构——更好更快的开发现代ASP.NET应用程序(续1) 今天在@张善友和@田园里的蟋蟀的博客看到微软“.Net社区虚拟大会”dotnetConf2015的信息,感谢他们的真诚付 ...
- Windows Phone 8.1 多媒体(1):相片
原文:Windows Phone 8.1 多媒体(1):相片 Windows Phone 8.1 多媒体(1):相片 Windows Phone 8.1 多媒体(2):视频 Windows Phone ...
- Facebook Hack 语言 简介
1. Hack 是什么? Hack 是一种基于HHVM(HipHop VM 是Facebook推出的用来执行PHP代码的虚拟机,它是一个PHP的JIT编译器,同时具有产生快速代码和即时编译的优点.)的 ...
- 高性能双端js模板
高性能双端js模板(新增filter)---simplite simplite是一款js实现的模板引擎,它能够完成浏览器端js模版和node服务器端js模板的数据渲染. 渲染性能十分突出. 支持浏览器 ...
- 第1章1节《MonkeyRunner源码剖析》概述:前言(原创)
天地会珠海分舵注:本来这一系列是准备出一本书的,详情请见早前博文“寻求合作伙伴编写<深入理解 MonkeyRunner>书籍“.但因为诸多原因,没有如愿.所以这里把草稿分享出来,所以错误在 ...
- WaitHandle、AutoResetEvent、ManualResetEvent
多线程中的锁系统(三)-WaitHandle.AutoResetEvent.ManualResetEvent 介绍 本章主要说下基于内核模式构造的线程同步方式,事件,信号量. 目录 一:理论 二:Wa ...
- dom03
鼠标事件: 键盘事件: //通过class获取元素,封装一个通过class获取元素的方法 //IE10以下不支持document.getElementByClass() function getByC ...
- [顶]ORACLE PL/SQL编程详解之二:PL/SQL块结构和组成元素(为山九仞,岂一日之功)
原文:[顶]ORACLE PL/SQL编程详解之二:PL/SQL块结构和组成元素(为山九仞,岂一日之功) [顶]ORACLE PL/SQL编程详解之二: PL/SQL块结构和组成元素(为山九仞,岂一日 ...
- userAgent,JS这么屌的用户代理,你造吗?——判断浏览器内核、浏览器、浏览器平台、windows操作系统版本、移动设备、游戏系统
1.识别浏览器呈现引擎 为了不在全局作用域中添加多余变量,这里使用单例模式(什么是单例模式?)来封装检测脚本.检测脚本的基本代码如下所示: var client = function() { var ...
- 增加VMWare开机画面时间,来防止快速跳过而无法进入BIOS
用记事本打开xx.vmx,在里面添加一行: bios.bootDelay = "30000" 意思是开机后,在开机画面里停留30秒.