Bool向量实现
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Bool向量实现相关的知识,希望对你有一定的参考价值。
有人可以告诉我这个向量实际上是如何工作的吗?特别是关于其operator=
类的operator bool
和VecProxy
以及主类的operator[]
。我知道减少内存使用量是必需的。就像bool是1字节一样,使用此类,我们可以为每个元素将其减少7位。我猜想VecProxy
需要分配每一位。
所以,这是代码:
template <>
class Vector<bool>
{
private:
typedef unsigned char byte;
size_t _size;
size_t _capacity;
size_t _byte_size;
byte* _data;
public:
Vector(size_t capacity = 0) : _size(0),
_capacity(capacity),
_byte_size(0),
_data(nullptr)
{
if (capacity > 0)
{
_data = new byte[capacity / 8 + (capacity % 8 != 0)];
if (!_data) throw "Out of memory";
}
}
class VecProxy
{
size_t _idx;
byte* _vec_ptr;
public:
VecProxy(size_t idx, byte* vecPtr) : _idx(idx), _vec_ptr(vecPtr) {}
VecProxy& operator=(bool val)
{
size_t char_idx = _idx / 8;
size_t bit_idx = _idx % 8;
if (val)
_vec_ptr[char_idx] |= 1 << bit_idx;
else
_vec_ptr[char_idx] &= ~(1 << bit_idx);
return *this;
}
operator bool()
{
size_t char_idx = _idx / 8;
size_t bit_idx = _idx % 8;
return (_vec_ptr[char_idx] >> char_idx) & 0x01;
}
};
VecProxy operator[](size_t idx)
{
if (idx >= _size) throw "Out of bounds";
return VecProxy(idx, _data);
}
Vector& resize(size_t new_size)
{
_capacity = new_size;
_size = _capacity < _size ? _capacity : _size;
_byte_size = _size / 8 + (_size % 8 != 0);
byte* tmp = new byte[_capacity / 8 + (_capacity % 8 != 0)];
if (!tmp) throw "Out of memory";
for (size_t i = 0; i < _byte_size; ++i)
tmp[i] = _data[i];
if (!_data)
delete[] _data;
_data = tmp;
}
Vector& push_back(bool val)
{
if (_size == _capacity)
{
if (_capacity < 10)
resize(_capacity + 10);
else
resize(_capacity * 1.5);
}
VecProxy(_size++, _data) = val;
return *this;
}
};
我有template<>
一定有点令人困惑。但是在.h
文件的其他部分中放置了标准vector
的主要实现。
所以,我想指定我的问题:
operator=
类的VecProxy
中实际发生了什么?我对if
感到非常困惑。return
的operator bool()
语句不清楚。- 但是我实际上知道了
operator[]
。
来自
像布尔值是1个字节,并且使用此类,我们可以将每个元素减少7位。
我们知道您了解每个位都有不同的含义,每个位代表一个不同的布尔值,然后将这些位一起打包在一起以节省空间。 为了再次获得布尔值,您必须找到正确的字节,然后找到该字节中的位。 _vec_ptr[char_idx]
查找正确的字节。 1 << bit_idx
产生将位隔离的bit mask。
让我们更仔细地看一下VecProxy
的operator=
:
VecProxy& operator=(bool val)
{
size_t char_idx = _idx / 8; // find byte index
size_t bit_idx = _idx % 8; // find bit index
if (val) // boolean is true, so bit must be set to 1
_vec_ptr[char_idx] |= 1 << bit_idx;
else // boolean false, so bit must be set to 0
_vec_ptr[char_idx] &= ~(1 << bit_idx);
return *this;
}
让功能进一步拆分:
VecProxy& operator=(bool val)
{
size_t char_idx = _idx / 8; // find byte index
size_t bit_idx = _idx % 8; // find bit index
byte & loc = _vec_ptr[char_idx]; // reference to byte that must be updated
byte mask = 1 << bit_idx; // mask isolating bit that must be updated
if (val) // boolean is true, so bit must be set to 1
loc |= mask;
else // boolean false, so bit must be set to 0
loc &= ~(mask);
return *this;
}
如果提供的bool
为val
,则该位需要为1。这很简单,您只需在位掩码中进行“或”即可。说我们要第三位
00000100
我们有
10101010
应用或
10101010 OR 00000100 = 10101110
但是如果值是假的,我们需要将该位设置为零。我们不能使用OR来做到这一点,但是可以使用AND来做到这一点。不幸的是,如果您这样做微不足道,则会得到
11111111 AND 00000000 = 00000000
这没用。您想保留其他位。您需要反转遮罩
11111111 AND 11111011 = 11111011
这就是~
运算符在loc &= ~(mask);
中所做的工作>事实证明,赋值运算符几乎是无用的。获得
VecProxy
的唯一方法是通过
VecProxy operator[](size_t idx)
并且它按值返回。它不能用于在Vector
中设置一个位。您可以在代理中设置一点,仅此而已。此更改无法传播到Vector
。
myvec[42] = true;
未能编译,因为它将更新临时副本。通过引用返回
VecProxy
,以便可以更新vector
是不平凡的重写。
现在让我们看一下运算符bool
operator bool()
{
size_t char_idx = _idx / 8;
size_t bit_idx = _idx % 8;
return (_vec_ptr[char_idx] >> char_idx) & 0x01;
}
此函数告诉您是否设置了此代理对象表示的位。它是如何做到的:我们找到带有_vec_ptr[char_idx]
的字节,然后将整个字节移开,将感兴趣的位带到第一位,并屏蔽掉除了感兴趣的位以外的所有内容。如果该位置1,则返回true。说我们从]开始>
10101010
我们想要第三位:
10101010 >> 2 == 00101010
((注意!注意符号扩展!如果字节是无符号的,您将得到11101010
以保持数字为负。在这里无关紧要,但是在其他情况下会得到您的帮助。)现在我们使用掩码0x01(
00000001
)检查该位是否已设置。
00101010 & 00000001 = 00000000
C ++从那里处理它,将0转换为false
的返回值
以上是关于Bool向量实现的主要内容,如果未能解决你的问题,请参考以下文章
Operator '||' cannot be applied to operands of type 'bool?' and 'bool?'(代码片段
Operator '||' cannot be applied to operands of type 'bool?' and 'bool?'(代码片段