C++ 头文件系列(vector)
简介
vector头文件包含vector的类模版以及该模版的显示特化版本vector< bool >。
vector是C++容器库中非常通用的一种容器,如果你不知道该决定使用哪一种容器,或者没有足够的理由使用其它容器,那么就用它,没错的!
从整体上来看,vector就像是一种动态数组,它拥有数组的所有功能并且能够动态增长。 它主要有以下性质:
- 序列性容器
- 动态增长
- 可定制的内存分配策略
内存分配器
如果在一些特殊的应用场景中,默认的内存分配策略拉低了运行效率,这时候自定义的内存分配其就会站出来帮你了~
内存分配器主要用在STL Containers中,为容器合理的分配内存,默认使用位于memory头文件中的allocator。 我们也可以自定义内存分配器,但需要满足一些要求:
Other allocators may be defined. Any class Alloc for which allocator_traits produces a valid instantiation with the appropriate members defined can be used as an allocator on standard containers (Alloc may or may not implement the functionality through member functions).
上面这段摘录的文字表明,任何能够实例化allocator_traits模版并且带有合适成员函数的类Alloc都能作为容器的内存分配器使用。 再来看allocator_traits:
The non-specialized version provides an interface that allows to use as allocator just any class that provides at least a public member type value_type and public member functions allocate and deallocate (see example).
这段话说,任何至少提供了一个公开成员类型value_type和公开成员函数allocate和deallocate的类都可以被允许作为内存分配器。
总的来说,自定义一个内存分配器,你最少需要:
- 定义value_type类型
- 定义allocate成员函数
- 定义deallocate成员函数
特殊函数
由于vector是动态数组,它的大部分设计是与array类模版类似的,这里就不再赘述了。 我们来看看那些不一样的的地方。
resize VS shrink_to_fit
这两个函数是比较特别的,从字面上看它们都是改变大小为固定值。 但实际上两者是有区别的,我们来看它们的函数原型:
void resize (size_type n);
void shrink_to_fit ();
一眼就能看出,两者的参数不一样:resize传入一个数值,作为新的容器大小;而shrink_to_fit则没有参数。 那我们不禁要问了,既然shrink_to_fit没有指定新的容器大小,它怎么改变呢?
这就揭示了两者语义上的不同----一个是改变大小至给定值,另一个是缩小容器容量(capacity)至容器大小(size)。 也就是说,它们影响的是容器的两个不同方面。 同时需要指出的是, shrink_to_fit调用发出的是请求,调用后容器容量可能被按预期缩小到容器大小了,也有可能比容器大小大;而resize调用发出的时命令,容器一定会被重新调整大小至给定值。
C接口
vector提供了一个接口以供开发者直接在内部数组(vector内部以数组实现)上直接对元素进行操作:
- value_type* data() noexcept;
顺道一提,vector与array一样,是元素之间的内存连续的(contiguous)。
vector< bool >显示特化
非常有意思的是vector这个模版显示特化了。
为什么
为什么会出现这样一个特殊的模版特化呢? 因为语言支持的最小单位一般是字节(char、unsigned char),而bool的语义意味着它只需要1bit的内存。 如果用1个字节来存储bool类型,会造成极大的内存浪费,出于内存的优化考虑,就出现了这么一个特殊的东西。
它的原理非常简单,就是把每个bool用1个bit来存储,所以1个字节可以存储8个bool(在常见的机器上)。 但是这也引出了一个麻烦的问题:在语义上,我们应该可以对bool赋值、取地址、取引用等。 但是bool等于bit这种实现方式意味着我们不能够那样做。 那怎么办了,这里使用了一个C++典型的惯用法----代理(Proxy),它把reference成员理性定义为该代理,用这个代理来将内部bit转换成bool。
Flip函数
该模版特化还包含了一个额外的函数----Flip。 顾名思义,就是将所有bool都“翻转”,true -> false, false -> true。
先前提到的reference代理也有这个函数,但它是将单个bool“翻转”。 vector< bool >类模版的flip函数可能就是通过该函数实现的。
C++ 头文件系列(vector)的更多相关文章
- C++ 头文件系列(array)
注意,该头文件仅在C++11中标准才开始出现. 简介 与语言内置的数组一样, array类模版支持几乎所有内置数组包含的特性: 顺序的(sequence) 内存连续的(contiguous stora ...
- C++ 头文件系列(queue)
简介 这个头文件定义了两个跟队列有关的类----quque.priority_queue,分别实现的是队列 和 优先队列这两个概念. 但是与这两个类模版与其它类模版(vector.array等)最大的 ...
- C++ 头文件系列(map)
简介 该头文件包含两个概念相似的容器----map.multimap. 而这两个容器反映的概念就是 映射. 这两个容器 相同 的属性有: 关联性 映射 动态增长 键(Key)唯一性 这两个不相同的属性 ...
- C++ 头文件系列 (bitset)
简介 该头文件有关位集,实际上是vector 位 位本质上对应bool的概念,只有0或1,true或false两种对立的值. 但很可惜,字节才是机器上最小的存储单元,所以bool基本上是由一个字节大小 ...
- C++ 头文件系列(iosfwd)
简介 输入输出历来都是语言的重要部分,在C++中,该库也是占据了相当大的一部分. C++的输入输出库是其遵循面向对象设计的结果,并结合了泛型编程. 以下是这些库类的关系图(箭头标示继承,白框表示摸板, ...
- C++ 头文件系列(stack)
简介 该头文件只含有一个类模版stack, 它实现栈的概念,是一个容器适配器(说实话,在写这篇随笔之前我都不知道有这么个类模版). 栈 栈只有一个重要的特性: LIFO(last-in first-o ...
- C++ 头文件系列(unordered_map、unordered_set)
简介 很明显,这两个头文件分别是map.set头文件对应的unordered版本. 所以它们有一个重要的性质就是: 乱序 如何乱序 这个unorder暗示着,这两个头文件中类的底层实现----Hash ...
- C++ 头文件系列(iterator)
简介 该头文件围绕迭代器展开,定义了一系列与迭代器有关的概念,但最最最重要的一点就是----它和其它容器一起实现了C++容器的Iterator设计模式. Iterators are a general ...
- C++ 头文件系列 (algorithm)
简介 algorithm头文件是C++的标准算法库,它主要应用在容器上. 因为所有的算法都是通过迭代器进行操作的,所以算法的运算实际上是和具体的数据结构相分离的 ,也就是说,具有低耦合性. 因此,任何 ...
随机推荐
- Raspberry Pi 上使用WN725N连接WIFI
系统版本 lee@Lee-RPi ~ $ uname -ar Linux Lee-RPi + # PREEMPT Thu Dec :: GMT armv6l GNU/Linux 这个版本的系统,已经集 ...
- CG中的数据变量类型
CG 中的数据变量类型有三: float:高精度浮点值,通常是32位. half:中精度浮点值.通常是16位,范围是-60000至+60000,它适合存储UV坐标,颜色值等. fixed:低精度浮点值 ...
- (中等) Hiho 1232 Couple Trees(15年北京网络赛F题),主席树+树链剖分。
"Couple Trees" are two trees, a husband tree and a wife tree. They are named because they ...
- MYSQL同步--主从同步问题集锦
1 同步停止,报错误: Could not find first log file name in binary log index file 数据库主从出错: Slave_IO_Running: ...
- Java加密解密字符串
http://www.cnblogs.com/vwpolo/archive/2012/07/18/2597232.html Java加密解密字符串 旧文重发:http://www.blogjava ...
- 比较全的JavaScript倒计时脚本
JavaScript倒计时在Web中用得非常广泛,比如常见的团购啊.还有什么值得期待的事情,都可以用到倒计时.现在举了四个例子,比如时间长的倒计时,小时倒计时,最简的倒计时,还有秒表等等,应该可以满足 ...
- Linux下部署
moto66@163.com 0144586wei 郭 2015/3/23 星期一 9:29:38 服务器密码:0144586Wei120.26.62.247
- Chapter5 – 碰撞检测
主人公能够放子弹了,虽然子弹看起来很美,但是怎么样来打到妖怪? 在这一章我们介绍一下最简单的碰撞检测方法去实现它. 首先第一个,我们有必要保存每个妖怪和子弹的指针,来够追踪他们的位置. 在这个游戏中我 ...
- 设置ubuntu下使用ls命令显示文件颜色显示
文件颜色属性: # Attribute codes: 字符属性# 00=none 01=bold 04=underscore 05=blink 07=reverse 08=concealed#00无 ...
- HDU 1813 Escape from Tetris
TMDTMD IDA*没跑了.什么是IDA*? 就是迭代深搜+A*估个价. 然而为什么调了一天? n<=2的时候我输出了东西.... 看了一天. #include<iostream> ...