重载下标运算符[]看了bitset的源码,发现要重载下标运算符[]内容还挺多的,作右(尚且这么称)时相对简单,只用
重载下标运算符[]
看了bitset的源码,发现要重载下标运算符[]内容还挺多的,作右值(尚且这么称)时相对简单,只用来测试。作左值时就比较麻烦,因为要修改它的值。
1、读
举个例子:
const bitset<10> b;bool tag;tag = b.test(2);tag = b[2];
上面第三句和第四句效果一样,都是测试b的下标为2的位是否为1。
当bitset为const时,operator[]执行的是:
bool operator[](size_t _Pos) const{// subscript nonmutable sequencereturn (test(_Pos));}可以看到,内部还是调用了test。
2、写
举个例子:
bitset<10> b;b.set(2);b[2] = 1; // 或b.operator[](2) = 1; // 或(b.operator[](2)).operator=(1);
上面的第二句和第三句效果一样,都是将b的下标为2的位设置为1,其实执行第三句时内部还是要调用set()的。
下面详细介绍:
#include <iostream>#include <bitset>using namespace std;int main(int argc, char **argv){bitset<10> b;// 第1步bitset<10>::reference r = b.operator[](2); // 函数名是operator[],实参是2,返回reference对象// 第2步r.operator=(1);// 这里r._Pbitset与&b相等(原理就是r用_Pbitset记住了b的地址),故改变了*_Pbitset也就改变了b// r无任何改变// 最后结果// r._Pbitset:[bitset][10](0,0,1,0,0,0,0,0,0,0)类型:std::bitset<10> *// b:[10](0,0,1,0,0,0,0,0,0,0)类型:std::bitset<10>// 两者是一致的return 0;}关于bitset类的定义,下面是个简化版:
// bitset类的简化版// 为了与库bitset区别,这里首字母大写class Bitset{public:class Reference{friend class Bitset; // 为了Reference外Bitset内的operator[]能访问Reference构造函数(private)public:Reference& operator=(bool _Val)// 第2步,还是要调用set{_PBitset->set(_Mypos, _Val);// r没变,但(*_PBitset)即b改变了return (*this);}private:Bitset *_PBitset;// Keysize_t _Mypos;Reference(Bitset& _Bitset, size_t _Pos) : _PBitset(&_Bitset), _Mypos(_Pos){// 构造函数}};Reference operator[](size_t _Pos) // 第1步{return (Reference(*this, _Pos));// 这个地方用法很怪!直接调用构造函数,创建一个无名的临时对象}Bitset& set(size_t _Pos, bool _Val = true){// 略}};下面摘录自《C++ Primer》(李师贤译)P94:
下标操作返回左值,因此可将下标操作作为赋值操作的左操作数。对下标操作的结果赋值是赋一个新值到相应的元素。
但我认为这是有前提的!如第一种情况,读const bitset时调用的operator[]返回的就是bool类型,而非reference类型。
关于bitset的源码,可以在VC\include\bitset中找到。
最后一个问题:
bitset<10> b;bool tag;tag = b[2];
这个测试又跟第一种不同了,其实这种情况比const那种测试常见地多,下次再介绍了。
