简介

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. CodeForces 614C Peter and Snow Blower

    简单计算几何,只要算出圆心到多边形上的最短距离和最长距离即可 #include<cstdio> #include<cstring> #include<cmath> ...

  2. uwsgi性能调忧

    摘要:调大uwsgi配置中 listen=1024的数目是提高并发能力最有效的办法.第二种方法是调大processes数目 发现总是超时报警 1  使用ab确定网络具体征况 [bre@dmp-1 ~] ...

  3. STM32之FreeRTOS

    STM32之FreeRTOS http://www.freertos.org/index.html http://www.freertos.org/a00090.html#ST http://www. ...

  4. Python正则表达式,统计分析nginx访问日志

    目标: 1.正则表达式 2.oop编程,统计nginx访问日志中不同IP地址出现的次数并排序 1.正则表达式 #!/usr/bin/env python # -*- coding: utf-8 -*- ...

  5. JS中的事件大全

    一般事件  onClick            鼠标点击事件,多用在某个对象控制的范围内的鼠标点击 onDblClick        鼠标双击事件 onMouseDown        鼠标上的按 ...

  6. ajax原理图解

    Ajax 原理图解 摘自: http://www.nowamagic.net/ajax/ajax_PicForAjaxPrinciple.php Ajax其实已经使用很久了,但一直也没有时间正经的找本 ...

  7. 网络IO模型

    同步(synchronous) IO和异步(asynchronous) IO,阻塞(blocking) IO和非阻塞(non-blocking)IO分别是什么,到底有什么区别?这个问题其实不同的人给出 ...

  8. MIPI-3

    上一篇文章讲了以下D_PHY层,这只是最底层的,针对于显示,上层由分出了四种,由专门的工作组进行定义,显示器方面叫做display wrok group,主要分为 DSC(display comman ...

  9. stm8的独立看门狗与窗口看门狗

    STM8拥有两个硬件看门狗,分别叫做独立看门狗和窗口看门狗 独立看门狗的框图如下 我们可以看到,独立看门狗的时钟来自于LSI内部低速振荡器,经过二分频到达看门狗外设单元,在经过一个七位的预分频到达计数 ...

  10. 浅谈一个网页打开的全过程(涉及DNS、CDN、Nginx负载均衡等)

    1.概要 从用户在浏览器输入域名开始,到web页面加载完毕,这是一个说复杂不复杂,说简单不简单的过程,下文暂且把这个过程称作网页加载过程.下面我将依靠自己的经验,总结一下整个过程.如有错漏,欢迎指正. ...