【问题标题】:bit vectors in c++ [closed]C ++中的位向量[关闭]
【发布时间】:2011-12-19 18:26:28
【问题描述】:

最近我听说了位向量,但我真的找不到任何关于这个主题的有用信息或教程。你能推荐一本书或一个关于如何实现你自己的位向量类的快速教程吗?谢谢。

---/// 我无法发布自己问题的答案,所以我决定编辑这篇文章。这是我刚刚发现的内容:“游戏程序员的数据结构 - Ron Penton 和 Andre Lamothe”。第 4 章,位向量。这本书对位向量进行了详尽的解释,以及如何自己制作位向量类。玩得开心。

【问题讨论】:

  • 您想了解关于位向量的哪些内容?在 C++ 中,您通常会为此使用 std::bitsetstd::vector<bool>
  • 好吧,我什至不知道它们有什么用,所以什么都可以)
  • 我不知道一大堆事情。你必须学习才能进步)
  • 因为我在一本关于数据结构的书中读到了位向量。但它没有提供有关它们的信息。我很好奇。
  • @jalf:我不同意。我想我给了 OP 一个有用的答案。一个简单的小实现(包含基本要素)以及简短的解释。

标签: c++ bitvector


【解决方案1】:

这是一个非常简单的静态大小的位向量实现。它需要 C++11 才能运行,因为它依赖于 <cstdint> 标头,但此标头很常见,因为它基于 C99 功能。在紧要关头,您可以使用 C <stdint.h> 标头并简单地使用全局命名空间中的类型。

注意:这是即时输入的,根本没有经过测试。我什至没有验证它会编译。所以,可能会有错误。

#include <cstdint>  // ::std::uint64_t type
#include <cstddef> // ::std::size_t type
#include <algorithm>

class my_bitvector_base {
 protected:
   class bitref { // Prevent this class from being used anywhere else.
    public:
      bitref(::std::uint64_t &an_int, ::std::uint64_t mask)
           : an_int_(an_int), mask_(mask)
      {
      }

      const bitref &operator =(bool val) {
         if (val) {
            an_int_ |= mask_;
         } else {
            an_int_ &= ~mask_;
         }
         return *this;
      }
      const bitref &operator =(const bitref &br) {
         return this->operator =(bool(br));
      }
      operator bool() const {
         return ((an_int_ & mask_) != 0) ? true : false;
      }

    private:
      ::std::uint64_t &an_int_;
      ::std::uint64_t mask_;
   };
};

template < ::std::size_t Size >
class my_bitvector : public my_bitvector_base {
 private:
   static constexpr ::std::size_t numints = ((Size + 63) / 64);
 public:
   my_bitvector() { ::std::fill(array, array + numints, 0); }

   bool operator [](::std::size_t bitnum) const {
      const ::std::size_t bytenum = bit / 64;
      bitnum = bitnum % 64;
      return ((ints_[bytenum] & (::std::uint64_t(1) << bitnum)) != 0) ? true : false;
   }
   bitref operator[](::std::size_t bitnum) {
      const ::std::size_t bytenum = bit / 64;
      bitnum = bitnum % 64;
      ::std::uint64_t mask = ::std::uint64_t(1) << bitnum;
      return bitref(ints_[bytenum], mask);
   }

 private:
   ::std::uint64_t ints_[numints];
};

// Example uses
void test()
{
    my_bitvector<70> bits; // A 70 bit long bit vector initialized to all false
    bits[1] = true; // Set bit 1 to true
    bool abit = bits[1]; // abit should be true.
    abit = bits[69]; // abit should be false.
}

整个my_bitvector_base 就是创建一种私有类型。您可以在派生类的接口或实现中提及它,因为它是protected,但您不能在其他上下文中提及它。这可以防止人们存储bitref 的副本。这一点很重要,因为 bitref 仅真正存在以允许分配给 operator [] 的结果,因为 C++ 标准委员会在他们所有的智慧中都没有实现 operator []= 或类似的东西来分配给数组元素。

如您所见,位向量基本上是位数组。更高级的位向量将模拟一个“无限”位数组,全部初始化为真或假。他们通过跟踪已设置的最后一位和之前的所有位来做到这一点。如果你在那之后再要求一点,他们只会返回初始化的值。

一个好的位向量也将实现operator &amp; 和其他类似的细节,因此它们在位操作操作方面表现得有点像一个非常大的无符号整数。

【讨论】:

  • bitset 有什么区别(如果有)?
  • @ceztko - ::std::bitset 在我写这篇文章的时候可能还不存在。
【解决方案2】:

vector 是向量模板的特化。一个普通的 bool 变量至少需要一个字节,但由于 bool 只 有两种状态向量的理想实现是这样的 每个布尔值只需要一位。这意味着迭代器必须是 特殊定义,不能为 bool*。

来自 Bruce Eckel 的 Thinking CPP Vol-2 第 4 章:STL 容器和迭代器

这本书可以在以下位置免费下载 http://www.mindviewinc.com/Books/downloads.html 它包含有关位和 C++ 的更多信息

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-05-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多