底层原理
vector<bool>本质上并不是一个STL容器,他底层通过位压缩技术,将每个bool值压缩为1位来进行存储,以减小向量对象的内存占用。
使用限制
首先,vector<bool>不像其他类型的vector数组,它的元素并不是真正意义上的bool类型,而是被包装在一个特殊的对象中。这意味着vector<bool>元素不能被当作普通的bool值进行操作。例如,不能对其执行引用操作,不能将其传递给期望bool值的函数等。
其次,由于使用位压缩技术,vector<bool>的迭代器行为也与其他类型的vector不同。在vector<bool>中使用迭代器访问元素时,迭代器返回的是一个代理对象而不是真正的引用,从而可能会引发一些意外的行为。
vector<bool> array { true, false, false };
bool b = array[0]
auto c = array[0]
b = false;
std::cout << array[0] << std::endl; // 输出是true
c = false;
std::cout << array[0] << std::endl; // 输出是false,这里没有使用auto&,但还是改变了原始数组
另外,由于使用了位压缩技术,vector<bool>的内存布局可能会导致对立案续元素的访问效率低下,因为访问单个bite比访问字节或者更大的数据单元更复杂,可能会影响一些需要频繁访问元素操作的性能。
建议
如果需要存储布尔值的向量,建议使用其他容器,例如vector<char>或vector<int>等。
底层实现
若对vector<bool>底层实现比较感兴趣的童鞋可以继续阅读。在c++标准中,没有bit类型,GNU-STL将unsigned log定义为一个_Bit_type,共有64个比特,可以存储64个bool类型变量。若要让使用者像正常vector一样使用vector<bool>,那么vector<bool>底层就必须实现将bool转成_Bit_type对象来存储以及将_Bit_type转成bool。
std::_Bit_reference
用来将bool类型变量映射到_Bit_type中的bit中,该类也是vector<bool>中的基本存储单位(使用[]返回值类型就是std::Bit_reference而不是bool类型对象,但是可以隐式转换为bool对象,例如上面代码中bool b = array[0])。
其次,该类型也能接受bool变量的赋值(将其存到某个_Bit_type的某个bit上)
std::_Bit_iterator_base
vector<bool>中的迭代器是基于std::_Bit_iterator实现的,其父类为std::_Bit_iterator_Base。_Bit_iterator_Base中有两个主要的成员变量:
1. _M_P: 指向_Bit_type
2. _M_offset: 指向当前正在遍历的_M_p_中第_M_offset个bit
使用这两个字段便可以定位到某个特定的bit所处的位置。(由此也可以理解为什么vector<bool>访问元素比较慢)