简介

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. codeforce 611A New Year and Days

    #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> using ...

  2. iframe载入等待

    <style> #pageloading{position:absolute; left:0px; top:0px;background:white url('../images/load ...

  3. iframe与父页面的js通信

    1.父页面调用iframe中的函数: document.getElementById('myframe').contentWidow.fun1(); 2.在iframe中调用父页面中的函数: wind ...

  4. C#WinForm中复制、粘贴文本到剪贴板

    //复制: private void button1_Click(object sender, System.EventArgs e) {   if(textBox1.SelectedText != ...

  5. ibatis的动态sql

    1.介绍 <select id="getUsers" parameterClass="user" resultMap="get-user-res ...

  6. Sencha Extjs4.2 皮肤制作

    1                 UI组件基础 学习ExtJs就是学习组件的使用.ExtJs4对框架进行了重构,其中最重要的就是形成了一个结构及层次分明的组件体系,由这些组件形成了Ext的控件. E ...

  7. (简单) POJ 2492 A Bug's Life,二分染色。

    Description Background Professor Hopper is researching the sexual behavior of a rare species of bugs ...

  8. Spring--注入类型--setter

    setter注入: package com.bjsxt.service; import com.bjsxt.dao.UserDAO; import com.bjsxt.model.User; publ ...

  9. Codeforces#355

    大小号刷题,大号,被查重,悲剧,最后小号过了3题 A题: 分析:大于h的+2,小于等于h的+1 #include <iostream> #include <cstdio> #i ...

  10. STM32串口寄存器操作(转)

    源:STM32串口寄存器操作 //USART.C /************************************************************************** ...