std::bitset使用

本文深入探讨C++标准库中的bitset模板,讲解其初始化、位操作符重载、访问、赋值和其他函数,如count、size、any、none、all等,并介绍如何将bitset转换为字符串、unsigned long和unsigned long long。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

std::bitset

bitset就像一个bool类型的数组一样,但是有空间优化——bitset中的一个元素只占1 bit。

bitset有一个特性:整数类型和布尔数组都能转化成bitset。

在定义bitset时,要明确bitset含有多少位,须在尖括号内给出它的长度值:给出的长度值必须是常量表达式

如果想用动态的bit数组,可以试试vector<bool>,vector<bool>是vector的一个模板特化,注意bool类型是8 bits,但是vector<bool>内部也会进行空间优化,vector< bool>里面不是一个Byte一个Byte储存的,而是一个bit一个bit储存的。

但是不提倡使用vector,
因为它不是容器,不容纳bool类型,因为vector 打包 bool 以节省空间,每个保存在“vector”中的“bool”占用一个单独的bit。
同时禁止有指向单个比特的指针
vector c{ false, true, false, true, false };
&tmp = c[0]; //错误,不能编译,对于引用来说,因为c[0]不是一个左值
bool *p = &c[0]; //错误,不能编译,因为无法将一个临时量地址给绑定到指针

c++中bool数组与bitset,vector的使用与占用空间大小对比

所以在实现位图这种结构时,如果bitset,vector<bool>都不适合的话,就得自己实现位图结构,然后自定义其中的置位为1,和置位为0的函数了。

模板文件声明

//注意bitset中存储的最大bits数由模板参数N决定,N必须给定一个常量表达式
template <size_t N> class bitset;

因为上面的size_t N决定了bitset最多存储的位数,所以得先看看size_t的定义
关于size_t定义
  size_t是一种数据相关的无符号类型,它被设计得足够大以便能够内存中任意对象的大小。在cstddef头文件中定义了size_t类型,这个文件是C标准库stddef.h头文件的C++版本
  size_t的取值与机器相关,在32位系统中size_t是4字节的,而在64位系统中,size_t是8字节的,该类型可以增强程序的可移植性

头文件

#include<bitset>

初始化

//默认无参构造,N位bits都为0
constexpr bitset() noexcept;
//用unsigned long long val填充 N位bitset
constexpr bitset (unsigned long long val) noexcept;

//用只含'0'/'1'字符的字符串去填充N位bitset
template <class charT, class traits, class Alloc>
  explicit bitset (const basic_string<charT,traits,Alloc>& str,
    typename basic_string<charT,traits,Alloc>::size_type pos = 0,
    typename basic_string<charT,traits,Alloc>::size_type n =
      basic_string<charT,traits,Alloc>::npos,
    charT zero = charT('0'), charT one = charT('1'));
    
//用只含'0'/'1'字符的字符串去填充N位bitset
template <class charT>
  explicit bitset (const charT* str,
    typename basic_string<charT>::size_type n = basic_string<charT>::npos,
    charT zero = charT('0'), charT one = charT('1'));

在定义bitset时,要明确bitset含有多少位,须在尖括号内给出它的长度值:给出的长度值必须是常量表达式
示例

// constructing bitsets
#include <iostream>       // std::cout
#include <string>         // std::string
#include <bitset>         // std::bitset
int main (){  
    std::bitset<16> foo;  //无参构造,长度为16,默认每一位为0
    std::bitset<16> bar (0xfa2);//长度为16,二进制保存,前面用0补充  
    std::bitset<16> baz (std::string("0101111001"));  //长度为16,前面用0补充
    //看一下bitset<16>是不是只占2字节(16位)
    std::cout<<"sizeof(bitset<16>)= "<<sizeof(baz)<<std::endl;
    //看一下size_t N表示的最大值,也即bitset最大bit容量(8字节)
    std::cout<<"sizeof(size_t)= "<<sizeof(size_t)<<std::endl;
    
    std::cout << "foo: " << foo << '\n';  std::cout << "bar: " << bar << '\n';
    std::cout << "baz: " << baz << '\n';
    system("pause");  
    return 0;
  }

在这里插入图片描述
size_t N最大为LONG_LONG_MAX

#define LONG_LONG_MAX 9223372036854775807ll

注意:

  • 用字符串构造时,字符串只能包含 ‘0’ 或 ‘1’ ,否则会抛出异常。
  • 构造时,需在<>中表明bitset 的大小(即size)。
  • 在进行有参构造时,参数为整数时
    若参数的二进制表示比bitset的size小,则在前面补0;若参数的二进制表示比bitset的size大,取整数参数后面部分。
  • 在进行有参构造时,参数为字符串时,若字符数比bitset的size小,则在前面补’0’;若字符数比bitset的size大,取字符串前面部分。

重载的位操作符

http://www.cplusplus.com/reference/bitset/bitset/operators/

bitset& operator&= (const bitset& rhs) noexcept;
bitset& operator|= (const bitset& rhs) noexcept;
bitset& operator^= (const bitset& rhs) noexcept;
bitset& operator<<= (size_t pos) noexcept;
bitset& operator>>= (size_t pos) noexcept;
bitset operator~() const noexcept;
bitset operator<<(size_t pos) const noexcept;
bitset operator>>(size_t pos) const noexcept;
bool operator== (const bitset& rhs) const noexcept;
bool operator!= (const bitset& rhs) const noexcept;

non-member functionstemplate<size_t N>
  bitset<N> operator& (const bitset<N>& lhs, const bitset<N>& rhs) noexcept;
  
template<size_t N>
  bitset<N> operator| (const bitset<N>& lhs, const bitset<N>& rhs) noexcept;
template<size_t N>
  bitset<N> operator^ (const bitset<N>& lhs, const bitset<N>& rhs) noexcept;
  
iostream inserters/extractorstemplate<class charT, class traits, size_t N>
  basic_istream<charT, traits>&
    operator>> (basic_istream<charT,traits>& is, bitset<N>& rhs);
    
template<class charT, class traits, size_t N>
  basic_ostream<charT, traits>&
    operator<< (basic_ostream<charT,traits>& os, const bitset<N>& rhs);

示例

// bitset operators
#include <iostream>       // std::cout
#include <string>         // std::string
#include <bitset>         // std::bitset

int main ()
{
  std::bitset<4> foo (std::string("1001"));
  std::bitset<4> bar (std::string("0011"));

  std::cout << (foo^=bar) << '\n';       // 1010 (XOR,assign)
  std::cout << (foo&=bar) << '\n';       // 0010 (AND,assign)
  std::cout << (foo|=bar) << '\n';       // 0011 (OR,assign)

  std::cout << (foo<<=2) << '\n';        // 1100 (SHL,assign)
  std::cout << (foo>>=1) << '\n';        // 0110 (SHR,assign)

  std::cout << (~bar) << '\n';           // 1100 (NOT)
  std::cout << (bar<<1) << '\n';         // 0110 (SHL)
  std::cout << (bar>>1) << '\n';         // 0001 (SHR)

  std::cout << (foo==bar) << '\n';       // false (0110==0011)
  std::cout << (foo!=bar) << '\n';       // true  (0110!=0011)

  std::cout << (foo&bar) << '\n';        // 0010
  std::cout << (foo|bar) << '\n';        // 0111
  std::cout << (foo^bar) << '\n';        // 0101

  return 0;
}

访问

bitset中的每个元素bit都能单独被访问。

  • operator[ ]:获取某位的数据,pos越界时会造成越界访问。
     //返回的是bool类型
     bool operator[] (size_t pos) const;
     //返回的是reference
     reference operator[] (size_t pos);

//reference是bitset内的嵌套类,
//主要实现的功能是把一个bool赋值给reference可以修改bitset中对应位置的值。
/*
class bitset::reference {
  friend class bitset;
  reference() noexcept;                               // no public constructor
public:
  ~reference();
  operator bool() const noexcept;                     // convert to bool
  reference& operator= (bool x) noexcept;             // assign bool
  reference& operator= (const reference& x) noexcept; // assign bit
  reference& flip() noexcept;                         // flip bit value
  bool operator~() const noexcept;                    // return inverse value
}
*/

示例:

// bitset::operator[]
#include <iostream>       // std::cout
#include <bitset>         // std::bitset

int main ()
{
  std::bitset<4> foo;

  foo[1]=1;             // 0010
  //将bool赋值给reference,修改对应的bit
  foo[2]=foo[1];        // 0110

  std::cout << "foo: " << foo << '\n';

  return 0;
}
  • test: 返回bitset中pos位置的值
    test与上面的operator[ ]的区别是test不会越界访问,
    当pos越界时会抛出out_of_range
//返回值为bool
bool test (size_t pos) const;

赋值

  • set:置1函数
//无参时,所有位置1
bitset& set() noexcept;
//pos位置1
bitset& set (size_t pos, bool val = true);
  • reset:置0函数
//无参时,所有位置0
bitset& reset() noexcept;
//pos位置0
bitset& reset (size_t pos);
  • flip:取反函数
//无参时,将所有位取反
bitset& flip() noexcept;
//将pos位取反
bitset& flip (size_t pos);

其他函数

  • count:bitset中1的位数
size_t count() const noexcept;
  • size:size函数用来求bitset的大小,即bitset中有多少bits
constexpr size_t size() noexcept;
  • any:bitset中只要有任何一位被置为1,则返回true
bool any() const noexcept;
  • none:bitset中没有任何一位被置为1,则返回true.
bool none() const noexcept;
  • all :bitset中所有位被置为1,则返回true
bool all() const noexcept;

转换

  • to_string:bitset转字符串
// bitset::to_string
#include <iostream>       // std::cout
#include <string>         // std::string
#include <bitset>         // std::bitset

int main ()
{
  std::bitset<4> mybits;     // mybits: 0000
  mybits.set();              // mybits: 1111

  std::string mystring =
    mybits.to_string<char,std::string::traits_type,std::string::allocator_type>();

  std::cout << "mystring: " << mystring << '\n';

  return 0;
}
  • to_ulong:bitset转换成unsigned long
unsigned long to_ulong() const;
// bitset::to_ulong
#include <iostream>       // std::cout
#include <bitset>         // std::bitset

int main ()
{
  std::bitset<4> foo;     // foo: 0000
  foo.set();              // foo: 1111

  std::cout << foo << " as an integer is: " << foo.to_ulong() << '\n';

  return 0;
}
  • to_ullong:bitset转换成unsigned long long
unsigned long long to_ullong() const;
// bitset::to_ullong
#include <iostream>       // std::cout
#include <bitset>         // std::bitset

int main ()
{
  std::bitset<4> foo;     // foo: 0000
  foo.set();              // foo: 1111

  std::cout << foo << " as an integer is: " << foo.to_ullong() << '\n';

  return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值