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]; //错误,不能编译,因为无法将一个临时量地址给绑定到指针
所以在实现位图这种结构时,如果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;
}