vector,被称为“最好的数组”,凭借其动态扩展能力和丰富的成员函数深受c++程序员和算竟选手喜爱,大家对此深信不疑。有一天,你听到个消息说:vector<bool>不是STL容器!此时,大家心里恍如晴天霹雳:要知道vector是世界上最好的序列式容器,谁敢在此质疑vector的完美设计?起初,笔者也同大家一样感到莫名其妙,迅速打开dev,创建vector<bool>看看能不能访问元素,能不能修改元素。一顿操作下来,完全没有问题啊!那为什么要说vector<bool>不是STL容器呢?通过查阅资料和总结,我们得出结论:vector<bool>不是STL容器!原因在于vector存储bool值的机制:
当我们创建一个数组时:
vector<int> v{1,2,3,4,5};//创建一个整型vector
元素会像这样被存到容器里:
根据sizeof(int)=4,所以是共占20个字节,一个字节是8个位,也就是160个位。
但是,当我们存储bool类型值时,它却变成了这样:
对的,读者没猜错,它把bool值存在了一个字节里。我们都知道,二进制世界只有0、1,也就是说,bool类型理论上一个位就能解决!实际编译时,通过sizeof(bool)=1我们发现,bool的存储实际上是1个字节,也就是8个位。也就是说,vector机制存储的并不是实际大小的bool,而是进行了优化,把他们存位上,进而优化内存!如何验证这个说法呢?无需复杂的验证,我们只需要取址&就好了:
#include<bits/stdc++.h> /* vector<bool>不是STL容器! */ using namespace std; void test() { vector<bool> v{true,true,false,false,false}; cout << "查看第一个元素的地址是:" << &v[0] << '\n'; } int main(){ test(); return 0; }
按下f11进行编译,红行报错,内容是:[Error] taking address of temporary [-fpermissive]。啥意思,就是无法取址呗!要知道,内存按字节编址,取址的单位是字节,位是没有地址的,说明vector<bool>是按位存而不是字节存。此行为严重违反模板的通用性,无法使用指针操作内存。
/*数据类型是T,存在v容器且v容器内至少有一个元素,此时能够对v容器内元素进行指针操作:*/ T * t = &v[0];
为了实现完美容器,将bool类型转位来存,这是多么浪漫而又宝贵的思想,只用1/8字节就能实现一个bool的存储,在那个内存寸土寸金的时代,无疑是最佳的选择!可是在当下看来,无疑是捡了芝麻丢了西瓜,给vector容器带来致命缺陷:
1:最直接的问题就是无法操作指针。(冷知识,&引用底层是通过指针操作实现的)
2:无法实现与C API接口耦合。
3:高并发编程造成操作冲突。
4:性能并不比普通bool类型的数组高。
那我们该如何解决呢?
1:那就少用或是禁用vector<bool>,使用普通数组实现。
2:使用其他容器进行bool元素存储,像list、array等。
3:能力高的话自己封装一个类来个性化设计bool容器。
C语言网提供由在职研发工程师或ACM蓝桥杯竞赛优秀选手录制的视频教程,并配有习题和答疑,点击了解:
一点编程也不会写的:零基础C语言学练课程
解决困扰你多年的C语言疑难杂症特性的C语言进阶课程
从零到写出一个爬虫的Python编程课程
只会语法写不出代码?手把手带你写100个编程真题的编程百练课程
信息学奥赛或C++选手的 必学C++课程
蓝桥杯ACM、信息学奥赛的必学课程:算法竞赛课入门课程
手把手讲解近五年真题的蓝桥杯辅导课程