为何调用std::vector<bool>::reserve(10)后容量变为64?
std::vector<bool>::reserve(10)会得到容量64? 这个现象是旧版本libstdc++(也就是你用的g++5.4配套的标准库)中std::vector<bool>特化实现的正常行为,背后主要有这几个原因:
1. 位压缩带来的内存分配粒度差异
std::vector<bool>是C++标准库中专门做空间优化的特化版本,它把多个bool值打包成单个字节(或更大的机器字)存储,而不是像普通vector<T>那样每个元素占独立的内存单元。
当你调用reserve(10)时,你请求的是能容纳10个位的空间,但底层内存分配器是按**字节(或更大的块)**来分配内存的,而且标准库实现有权选择比实际需求更大的分配量——只要保证容量至少能容纳你请求的元素数量就行。
2. 旧版libstdc++的具体实现逻辑
在你使用的g5.4对应的libstdc版本中,std::vector<bool>的内部存储很可能是以64位(8字节)为基本块单位来分配的。也就是说,即使你只需要10位,它也会直接分配一整块64位的空间,这样后续添加元素时不需要频繁重新分配,提升效率。
你可以做个小验证:如果调用reserve(65),你大概率会看到容量变成128——这就说明它是按64位的倍数来分配内存的。
3. C++标准对reserve的宽松要求
C++标准只规定reserve(n)必须保证容器的容量至少为n,完全没有要求容量必须恰好等于n。对于普通的vector<T>,实现通常会尽量贴近请求的大小,但对于std::vector<bool>这种特殊的位容器,实现者有更大的自由度来选择分配策略,只要满足最小容量要求即可。
至于你提到的cppreference上的那几个特性,和这个现象直接相关的是第三点:它不使用std::allocator_traits::construct来构造位值——因为它不需要构造bool对象,只是直接操作内存中的位,所以分配内存的逻辑可以更灵活,不用严格按单个元素的大小来计算分配量。
简单来说,这不是bug,是旧版libstdc为了效率和实现简便做出的设计选择,完全符合C标准的要求。
内容的提问来源于stack exchange,提问作者Eduardo J. Sanchez

