STL源碼分析--bitset

更多精彩內容,請關注微信公衆號:後端技術小屋c++

1 相關頭文件

bitset

2 bitset

bitset中STL中用於表示位圖的容器,它支持讀寫特定bit、從整數或字符串生成bitset對象。bitset大小經過模板參數指定,一旦編譯器肯定便沒法變動,這一點與vector<bool>有差別。後端

2.1 數據結構

bitset_Base_bitset的派生類。_Base_bitset中包含一個長度_Nw,類型unsigned long的數組,其中_Nw經過模板參數指定。在64位系統中,unsigned long長度爲8 Byte。數組

注意,這裏_Nb不必定是8 * sizeof(unsigned)的整數倍,因此須要宏__BITSET_WORDS對其進行向上取整操做。微信

template<size_t _Nb>
class bitset : private _Base_bitset<__BITSET_WORDS(_Nb)>
{
private:
  typedef _Base_bitset<__BITSET_WORDS(_Nb)> _Base;
  typedef unsigned long _WordT;
  ...
}

template<size_t _Nw>
struct _Base_bitset {
  typedef unsigned long _WordT;

  _WordT _M_w[_Nw];                // 0 is the least significant word.
  ...
}

2.2 重要接口

  • 從整數構造bitset
    首先對數組清零,而後將__val值賦給數組的首個元素。最後使用_M_do_sanitize判斷_Nb是否是sizeof(unsigned long)的整數倍,不然將right padding bits所有置爲1。
bitset(unsigned long __val) : _Base_bitset<__BITSET_WORDS(_Nb)>(__val)
    { _M_do_sanitize(); }

  _Base_bitset(unsigned long __val) {
    _M_do_reset();
    _M_w[0] = __val;
  }

  void _M_do_sanitize() {
    _Sanitize<_Nb%__BITS_PER_WORD>::_M_do_sanitize(this->_M_hiword());
  }

template <size_t _Extrabits> struct _Sanitize {
  static void _M_do_sanitize(unsigned long& __val)
    { __val &= ~((~static_cast<unsigned long>(0)) << _Extrabits); }
};

__STL_TEMPLATE_NULL struct _Sanitize<0> {
  static void _M_do_sanitize(unsigned long) {}
};
  • 從字符串構造bitset
    由字符'0', '1'組成的字符串構造bitset。注意: 字符串從左到右,對應的bit在bitset中從右到左。由於字符串中, 左邊爲高位,bitset中右邊爲高位。
explicit bitset(const basic_string<char>& __s,
                  size_t __pos = 0,
                  size_t __n = basic_string<char>::npos)
    : _Base()
  {
    if (__pos > __s.size())
      __STL_THROW(out_of_range("bitset"));
    _M_copy_from_string(__s, __pos, __n);
  }
  • to_ulong: 將bitset轉化爲ulong類型數據結構

  • to_string: 將bitset轉化爲'0' '1'組成的字符串源碼分析

  • <<=: 邏輯左移,移出部分補零。注意:在實現上,數組_M_w中低位對應bitset中低位,所以,對bitset的左移操做其實就是對數組的右移操做,右移同理。若是移動位數是8 * sizeof(unsigned long)的整數倍,則直接移動數組中元素便可。this

const size_t __sub_offset = __BITS_PER_WORD - __offset;
      for (size_t __n = _Nw - 1; __n > __wshift; --__n)
        _M_w[__n] = (_M_w[__n - __wshift] << __offset) |
                    (_M_w[__n - __wshift - 1] >> __sub_offset);
      _M_w[__wshift] = _M_w[0] << __offset;
    }
  • >>=: 邏輯右移
const size_t __sub_offset = __BITS_PER_WORD - __offset;
      for (size_t __n = 0; __n < __limit; ++__n)
        _M_w[__n] = (_M_w[__n + __wshift] >> __offset) |
                    (_M_w[__n + __wshift + 1] << __sub_offset);
      _M_w[__limit] = _M_w[_Nw-1] >> __offset;
  • |=: 按位或
  • &=: 按位與
  • ^+: 按位異或
  • set: 置位
  • reset: 清零
  • flip: 翻轉
  • ~: 所有翻轉
  • count: count爲了快速計算bitset中1的個數,使用了查找表的技巧。查找表中key爲byte值,value爲該byte值中1的個數。count方法遍歷數組中每一個字節,經過查找表計算每一個字節中1的個數,並累加之。
  • size: 返回bitset大小
  • test: 判斷bitset中某位是否爲1
  • any: 判斷bitset中是否有至少一個1
  • none: 同any相反
  • all: 判斷bitset中是否全爲1

留下問題給讀者思考:爲什麼bitset中的數組類型是unsigned long而非unsigned char?code

推薦閱讀對象

更多精彩內容,請掃碼關注微信公衆號:後端技術小屋。若是以爲文章對你有幫助的話,請多多分享、轉發、在看。
二維碼接口

相關文章
相關標籤/搜索