标准库特殊设施
1 tuple类型
tuple是类似pair的模板,不同tuple类型的成员类型也不相同,但一个tuple可以有任意数量的成员
操作 | 描述 |
---|---|
tuple<T1, T2, ..., Tn> t; |
t是一个tuple,成员数为n,第i个成员的类型为Ti |
tuple<T1, T2, ..., Tn> t(v1, v2, ..., vn); |
t是一个tuple,成员类型为T1...Tn ,每个成员用对应的初始化vi进行初始化 |
make_tuple(v1,v2, ...,vn) |
返回一个用给定初始值初始化的tuple。tuple的类型从初始值的类型推断 |
t1 == t2 |
当两个tuple具有相同数量的成员且成员对应相等时,两者相等 |
t1 != t2 |
只要有一个成员不等,就停止比较 |
t1 relop t2 |
tuple的关系运算使用字典序,两个tuple必须具有相同数量的成员。使用<运算符比较t1 的成员和t2 中的成员 |
get<i> (t) |
返回t的第i个数据成员的引用,tuple的所有成员都是public |
tuple_size<tupleType>::value |
一个类模板,可以通过一个tuple类型来初始化。其有一个名为value的public constexpr static 数据成员,类型为size_t,表示给定tuple类型中成员的数量 |
tuple_element<i, tupleType>::type |
一个类模板,可以通过一个整型常量和一个tuple类型来初始化。其有一个名为type的public成员,表示给定tuple类型中指定成员的类型 |
1.1 定义和初始化tuple
当定义一个tuple时,需要指出每个成员的类型:
tuple<size_t, size_t, size_t> threeD; //三个成员都设置为0
tuple<string, vector<double>, int, list<int>>
someVal("constants", {
3.14, 2.718}, 42, {
0,1,2,3,4,5})
tuple的这个构造函数是explicit的,因此必须使用直接初始化语法:
tuple<size_t, size_t, size_t> threeD{
1,2,3}; //三个成员都设置为0
访问tuple的成员
要访问tuple的成员,使用一个名为get的标准库函数模板,同时传递给get一个tuple对象,其返回指定成员的引用:
auto book = get<0>(item); //返回item的第一个成员
auto book = get<1>(item); //返回item的第二个成员
auto book = get<2>(item)/cnt; //返回item的最后一个成员
get<2>(item) *= 0.8; //打折20%
注意:尖括号中的值必须是一个整型常量表达式,从0开始计数,意味着get<0>
是第一个成员。
2 bitset类型
2.1 定义和初始化bitset
标准库定义bitset类,使得位运算的使用更为容易,其定义在头文件bitset
中。
bitset类是一个类模板,类似array类,具有固定的大小,因此当定义一个bitset时,需要声明其包含多少个二进制位:
bitset<32> bitvec(1U); //32位;低位为1,其他位为0
大小必须是一个常量表达式。其中编号从0开始的二进制位被称为低位,编号到31结束的二进制位被称为高位
操作 | 说明 |
---|---|
bitset<n> b; |
b有n位;每位均为0,此构造函数是一个constexpr |
bitset<n> b(u); |
b是unsigned long long 值u的低n位的拷贝,若n超出类型范围,则b中超出类型的高位被置0 |
bitset<n> b(s, pos, m, zero, one); |
b是string从位置pos 开始m个字符的拷贝。s只能包含字符zero或one;如果s包含任何其他字符,构造函数会抛出invalid——argument 异常。 |
bitset<n> b(cp, pos, zero, one); |
与是一个函数相同,但从cp 指向的字符数组中拷贝字符。若未提供m,则cp 必须指向一个C风格字符串。若提供了m,则从cp 开始必须至少有m个zero或one字符 |
接受一个string或一个字符指针的构造函数是explicit
。
用unsigned值初始化bitset
当使用一个整型值来初始化bitset时,此值将被转换为unsigned long long
类型并被当作位模式来处理。若bitset的大小大于一个unsigned long long
中的二进制位数,则剩余的高位被置为0。若bitset的大小小于一个unsigned long long
中的二进制位数,则只使用给定值中的低位,超出bitset大小的高位被丢弃:
//bitvecl比初始值小;初始值中的高位被丢弃
bitset<13> bitvecl1(0xbeef); //二进制位序列为1 1110 1110 1111
//bitvec2比初始值大;它的高位被置为0
bitset<20> bitvecl1(0xbeef); //二进制位序列为0000 1011 1110 1110 1111
//在64位机器中,long long 0ULL是个64个0比特,故~0ULL是64个1
bitset<128> bitvecl1(~0ULL); //0~63位为1;63~127位为0
从一个string初始化bitset
可以从一个string或一个字符数组指针来初始化bitset。两种情况下,字符都直接表示位模式。其中字符串中下标最小的字符对应高位。
bitset<32> bitvec("1100"); //2、3两位为1,剩余两位为0
如果string包含的字符数比bitset少,则bitset的高位被置为0
tip:string的下标编号与bitset恰好相反:string中下标最大的字符(最右字符)用来初始化bitset中的低位(下标为0的二进制位)
其它初始化方式:
string str("111111100000011001101");
bitset<32> bitvec5(str, 5, 4); //从str[5]开始的四个二进制位,1100
bitset<32> bitvec6(str, str.size() - 4); //使用最后四个字符
下图说明了上述拷贝过程:
2.2 bitset操作
bitset
操作定义了多种检测或设置一个或多个二进制位的方法,其操作如下表:
操作 | 描述 |
---|---|
b.any() |
b中是否存在置为的二进制位 |
b.all() |
b中所有位是否都置位了 |
b.none() |
b中不存在置位的二进制吗 |
b.count() |
b中置位的位数 |
b.size() |
一个constexpr ,返回b中的位数 |
b.test(pos) |
若pos 位置的位是置位的,则返回true,否则返回false |
b.set(pos, v) b.set() |
将位置pos 处的位设置为bool 值v。v默认为true,若未传递参数,则将b中所有位置位 |
b.reset(pos) b.reset() |
将位置pos 处的位复位或将b中的所有位复位 |
b.flip(pos) b.flip() |
改变位置pos 处的位的状态或改变b中每一位的状态 |
b[pos] |
访问b中位置pos 处的位;若b是const 的,则该位置位时b[pos] 返回一个bool 值true,否则返回false |
b.to_ulong() b.to_ullong() |
返回一个unsigned long 或一个unsigned long long 值,其位模式与b相同 |
b.to_string(zero, one) |