vector 特性
std::vector
std::vector
std::vector
不必作为连续数组存储元素
暴露类 std::vector
不使用 std::allocator_traits::construct 构造位值。
不保证同一容器中的不同元素能由不同线程同时修改。 api文档
底层实现
单独的libstdc++-v3/include/bits/stl_bvector.h实现
主要是存了bit pointer
vector 的空间优化
vector 的capacity
vector
std::vector<bool> data;
std::cout << data.size() << " " << data.capacity() << std::endl;
0 0
如果存入1个数字
std::vector<bool> data;
data.push_back(1);
std::cout << data.size() << " " << data.capacity() << std::endl;
1 64
存入3个数字:
std::vector<bool> data;
data.push_back(1);
data.push_back(2);
data.push_back(3);
std::cout << data.size() << " " << data.capacity() << std::endl;
3 64
可以看到,从存入第一个数字开始,capacity直接到了64
这是因为vector
vector 的capacity 变化
相反如果是vector
std::vector<int> data;
data.push_back(1);
std::cout << data.size() << " " << data.capacity() << std::endl;
1 1
存入3个int
std::vector<bool> data;
data.push_back(1);
data.push_back(2);
data.push_back(3);
std::cout << data.size() << " " << data.capacity() << std::endl;
3 4
vector取值
#include <iostream>
#include <vector>
int main() {
std::vector<bool> data;
data.push_back(1);
data.push_back(2);
data.push_back(3);
// auto &front = data.front();
std::cout << data.size() << " " << data.capacity() << " " << data.front() <<std::endl;
}
输出data.front() 是正常的, 但是如果打开注释,取左值引用,编译器会报错, vector
<source>: In function 'int main()':
<source>:10:29: error: cannot bind non-const lvalue reference of type 'std::_Bit_reference&' to an rvalue of type 'std::vector<bool>::reference'
10 | auto &front = data.front();
|
所以用operator[]的时候,正常容器返回的应该是一个对应元素的引用,但是对于vector< bool>实际上访问的是一个”proxy reference”而不是一个”true reference”,返回的是”std::vector< bool>:reference”类型的对象。
因为bit你是无法访问到地址的
正确取值方式
auto d = data[0];
修改d会影响到data
bool a = data[0];
过程中其实包含了bit转换到bool的过程
std::_Bit_reference
下面来看看怎么将一个bool类型变量映射到_Bit_type中的一个bit,这由类 std::_Bit_reference 实现的。
类 std::_Bit_reference 是 std::vector
比如,std::vector
实现如下:
struct _Bit_reference
{
_Bit_type* _M_p;
_Bit_type _M_mask;
_Bit_reference(_Bit_type *__x, _Bit_type __y)
: _M_p(__x), _M_mask(__y) {}
_Bit_reference() noexcept : _M_p(0), _M_mask(0) {}
_Bit_reference(const _Bit_reference &) = default;
///@brief 隐式转成 bool
/// bool state = vb[1]; 会触发此函数
operator bool() const noexcept
{ return !!(*_M_p & _M_mask); }
///@brief 将 _M_p 的 _M_mask 位,设置为 __x 状态
/// vb[1] = true; 会触发此函数
_Bit_reference& operator=(bool __x) noexcept
{
if (__x)
*_M_p |= _M_mask; // 1
else
*_M_p &= ~_M_mask;
return *this;
}
// @brief 这个函数实际上调用了:
// 1. 先调用了 operator bool() const noexcept
// 2. 在调用了 _Bit_reference& operator=(bool __x) noexcept
_Bit_reference& operator=(const _Bit_reference &__x) noexcept
{ return *this = bool(__x); }
bool operator==(const _Bit_reference &__x) const
{ return bool(*this) == bool(__x); }
bool operator<(const _Bit_reference &__x) const
{ return !bool(*this) && bool(__x); }
void flip() noexcept
{ *_M_p ^= _M_mask; }
};
参考
https://zh.cppreference.com/w/cpp/container/vector_bool
https://mp.weixin.qq.com/s/pkHfGjw8by8g1sbWhWKysw
https://blog.0xzhang.com/posts/%E8%B8%A9%E5%9D%91vector.html
https://www.youtube.com/watch?v=OP9IDIeicZE
https://blog.csdn.net/haolexiao/article/details/56837445