简介

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的类都可以被允许作为内存分配器

总的来说,自定义一个内存分配器,你最少需要

  1. 定义value_type类型
  2. 定义allocate成员函数
  3. 定义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)的更多相关文章

  1. C++ 头文件系列(array)

    注意,该头文件仅在C++11中标准才开始出现. 简介 与语言内置的数组一样, array类模版支持几乎所有内置数组包含的特性: 顺序的(sequence) 内存连续的(contiguous stora ...

  2. C++ 头文件系列(queue)

    简介 这个头文件定义了两个跟队列有关的类----quque.priority_queue,分别实现的是队列 和 优先队列这两个概念. 但是与这两个类模版与其它类模版(vector.array等)最大的 ...

  3. C++ 头文件系列(map)

    简介 该头文件包含两个概念相似的容器----map.multimap. 而这两个容器反映的概念就是 映射. 这两个容器 相同 的属性有: 关联性 映射 动态增长 键(Key)唯一性 这两个不相同的属性 ...

  4. C++ 头文件系列 (bitset)

    简介 该头文件有关位集,实际上是vector 位 位本质上对应bool的概念,只有0或1,true或false两种对立的值. 但很可惜,字节才是机器上最小的存储单元,所以bool基本上是由一个字节大小 ...

  5. C++ 头文件系列(iosfwd)

    简介 输入输出历来都是语言的重要部分,在C++中,该库也是占据了相当大的一部分. C++的输入输出库是其遵循面向对象设计的结果,并结合了泛型编程. 以下是这些库类的关系图(箭头标示继承,白框表示摸板, ...

  6. C++ 头文件系列(stack)

    简介 该头文件只含有一个类模版stack, 它实现栈的概念,是一个容器适配器(说实话,在写这篇随笔之前我都不知道有这么个类模版). 栈 栈只有一个重要的特性: LIFO(last-in first-o ...

  7. C++ 头文件系列(unordered_map、unordered_set)

    简介 很明显,这两个头文件分别是map.set头文件对应的unordered版本. 所以它们有一个重要的性质就是: 乱序 如何乱序 这个unorder暗示着,这两个头文件中类的底层实现----Hash ...

  8. C++ 头文件系列(iterator)

    简介 该头文件围绕迭代器展开,定义了一系列与迭代器有关的概念,但最最最重要的一点就是----它和其它容器一起实现了C++容器的Iterator设计模式. Iterators are a general ...

  9. C++ 头文件系列 (algorithm)

    简介 algorithm头文件是C++的标准算法库,它主要应用在容器上. 因为所有的算法都是通过迭代器进行操作的,所以算法的运算实际上是和具体的数据结构相分离的 ,也就是说,具有低耦合性. 因此,任何 ...

随机推荐

  1. Raspberry Pi 上使用WN725N连接WIFI

    系统版本 lee@Lee-RPi ~ $ uname -ar Linux Lee-RPi + # PREEMPT Thu Dec :: GMT armv6l GNU/Linux 这个版本的系统,已经集 ...

  2. CG中的数据变量类型

    CG 中的数据变量类型有三: float:高精度浮点值,通常是32位. half:中精度浮点值.通常是16位,范围是-60000至+60000,它适合存储UV坐标,颜色值等. fixed:低精度浮点值 ...

  3. (中等) Hiho 1232 Couple Trees(15年北京网络赛F题),主席树+树链剖分。

    "Couple Trees" are two trees, a husband tree and a wife tree. They are named because they ...

  4. MYSQL同步--主从同步问题集锦

    1  同步停止,报错误:  Could not find first log file name in binary log index file 数据库主从出错: Slave_IO_Running: ...

  5. Java加密解密字符串

    http://www.cnblogs.com/vwpolo/archive/2012/07/18/2597232.html Java加密解密字符串   旧文重发:http://www.blogjava ...

  6. 比较全的JavaScript倒计时脚本

    JavaScript倒计时在Web中用得非常广泛,比如常见的团购啊.还有什么值得期待的事情,都可以用到倒计时.现在举了四个例子,比如时间长的倒计时,小时倒计时,最简的倒计时,还有秒表等等,应该可以满足 ...

  7. Linux下部署

    moto66@163.com       0144586wei 郭 2015/3/23 星期一 9:29:38 服务器密码:0144586Wei120.26.62.247

  8. Chapter5 – 碰撞检测

    主人公能够放子弹了,虽然子弹看起来很美,但是怎么样来打到妖怪? 在这一章我们介绍一下最简单的碰撞检测方法去实现它. 首先第一个,我们有必要保存每个妖怪和子弹的指针,来够追踪他们的位置. 在这个游戏中我 ...

  9. 设置ubuntu下使用ls命令显示文件颜色显示

    文件颜色属性: # Attribute codes: 字符属性# 00=none 01=bold 04=underscore 05=blink 07=reverse 08=concealed#00无 ...

  10. HDU 1813 Escape from Tetris

    TMDTMD IDA*没跑了.什么是IDA*? 就是迭代深搜+A*估个价. 然而为什么调了一天? n<=2的时候我输出了东西.... 看了一天. #include<iostream> ...