位集参考

7
http://www.cplusplus.com/reference/stl/bitset/得知:

由于在大多数C++环境中不存在这样的小元素类型,因此使用特殊引用来访问各个元素,这些引用模仿了bool元素。

那么,这个位引用是如何工作的呢?

我所能想到的唯一方法是使用char的静态数组,但每个实例都需要在数组中存储其索引。由于每个引用实例至少具有size_t大小,这将破坏位集的紧凑性。此外,调整大小可能会很慢,而位操作应该很快。

4个回答

6
我认为你混淆了两件事情。
bitset类以紧凑的方式存储位,例如在char数组中,通常每个char有8位(但在“奇特”的平台上可能会有所不同)。
bitset::reference类提供了允许bitset类的用户拥有类似引用的对象来存储在bitset中的位的引用。
由于普通指针和引用没有足够的粒度来指向存储在bitset中的单个位(它们的最小粒度是char),因此这种类模仿了对位的假引用样式左值操作。这是必要的,特别是为了允许operator[]返回的值正常地作为左值工作(它可能构成其“正常”使用的99%)。在这种情况下,它可以被视为“代理对象”。
通过重载赋值运算符和转换为bool运算符来实现这种行为;bitset::reference类可能封装对父bitset对象的引用以及所引用的位的偏移量(字节+位),这些运算符用于检索和存储位的值。
---编辑---
实际上,g ++实现使bitset :: reference直接存储指向存储字节的内存字的指针以及该字中的位数。然而,这只是一种实现细节,用于提高性能。
顺便说一句,在库源代码中,我找到了一个非常简洁但清晰的解释bitset :: reference是什么以及它的作用。
  /**
   *  This encapsulates the concept of a single bit.  An instance of this
   *  class is a proxy for an actual bit; this way the individual bit
   *  operations are done as faster word-size bitwise instructions.
   *
   *  Most users will never need to use this class directly; conversions
   *  to and from bool are automatic and should be transparent.  Overloaded
   *  operators help to preserve the illusion.
   *
   *  (On a typical system, this <em>bit %reference</em> is 64
   *  times the size of an actual bit.  Ha.)
   */

1

我还没有查看STL源代码,但我期望Bitset引用包含指向实际bitset的指针和大小为size_t的位数。只有在尝试获取bitset元素的引用时才会创建引用。

正常使用bitset时,不太可能广泛使用引用(如果有的话),因此不应该有太多性能问题。而且,它在概念上类似于char类型。一个char通常是8位,但要存储对char的“引用”需要一个指针,因此通常是32或64位。


0

我从未查看过参考实现,但显然它必须通过引用知道它所指的位集,并且负责更改的位的索引。然后,它可以使用其余的位集接口来进行所需的更改。这可能非常高效。请注意,位集无法调整大小。


0

我不太确定你在问什么,但我可以告诉你一种访问字节中单个位的方法,这也许就是bitset所做的事情。请注意,以下代码不是我自己写的,而是微软规范(!)。

创建一个如下的结构体:

struct Byte
{
    bool bit1:1;
    bool bit2:1;
    bool bit3:1;
    bool bit4:1;
    bool bit5:1;
    bool bit6:1;
    bool bit7:1;
    bool bit8:1;
}

这段代码中的“:1”部分是位域。http://msdn.microsoft.com/en-us/library/ewwyfdbe(v=vs.80).aspx它们定义了变量所需占用的位数,因此在这个结构体中,有8个布尔值,每个占用1位。因此,“Byte”结构体的大小为1字节。

现在,如果您有一个字节的数据,比如一个字符,您可以将这个数据存储在一个Byte对象中,如下所示:

char a = 'a';
Byte oneByte;
oneByte = *(Byte*)(&a);   // Get the address of a (a pointer, basically), cast this  
                          // char* pointer to a Byte*,
                          // then use the reference operator to store the data that 
                          // this points to in the variable oneByte.

现在,您可以通过访问oneByte的bool成员变量来访问(和更改)单个位。为了再次将更改后的数据存储在char中,您可以执行以下操作:

char b;
b = *(char*)(&oneByte);   // Basically, this is the reverse of what you do to 
                          // store the char in a Byte.

我会尝试找到这种技术的来源,并给予应有的荣誉。

此外,我不完全确定这个答案是否对您有用。我理解您的问题是“如何处理对内部个别位的访问?”


问题涉及 C++ 标准库中的类 std::bitsetstd::bitset::reference - Matteo Italia
@Matteo Italia:我知道这一点,我把这个问题解释为询问这些类对位的访问是如何在内部实现的。 - Rycul

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接