1 可以使用下标操作的容器的下标引用
对容器的下标引用操作和我们对数组引用下标操作一样,千万不要去引用未定义的单元,否则你将..
以vector为例:
- vector<int> vec;
- for (int i = 0; i < 5; ++i)
- {
- vec[i] = 1;
- }
你不能这样做。因为根据vector的特性,我们定义的vec这个vector<int>类型变量目前没分配空间。我们的引用操作将会去引用为定义单元。引起内存错误。但我们若真要想这样为vec型变量赋值怎么办?
我们可以这样:
- vector<int> vec(10);
- for (int i = 0; i < 10; ++i)
- {
- vec[i] = 0;
- }
OK!You Can!因为此时vec变量已经有了10个int类型的内存空间。所以你可以对他进行引用。但此时我们仍然不可以利用赋值操作对下标为10及以后的单元进行引用。但我们可以使用cout来输出以后单元的内容,你样的引用不会出错。但若在第一种情况下我们使用cout来引用仍然出错。因为那时候vec根本没有内存单元,所以我们一切的下标引用都是错误的。而现在不一样了,虽然我们使用类似cout << vec[20] << endl;引用虽然已经出界,但它仍然指向已存在的内存单元,只不过是一个不在我们掌握范围内的内存单元罢了。但为什么我们不可以对这样的内存单元进行写操作呢?我想 一是因为我们没有对这样的单元有掌握权,即我们并没有想操作系统申请权限,二是因为操作系统的一个自我保护,若我们目前的下标操作指向了一个很重要的内存单元,若操作系统允许写操作,岂不是要出大问题了。呵呵。。
2 指针应注意的一些东西
若我们在程序别处已定义了一个类类型的指针,如:
- vector<int> *p = 0;
我们在此处想判断一下指针所指向的对象中第二个数是否为1;
我们该如何做呢?
- if ((*p)[1] == 1)
- {
- //do something
- }
这样做行吗?显然我们根据我们的目的直接写出了条件,但是我们还应该判断该指针所指的对象是否为空,否则它会影响我们的判断。甚至还有些对空对象对下标的引用会引起错误。如:vector;所以我们对于本题我们该这么些。
- if ( !p->empty() && (*p)[1] == 1)
- {
- //do something;
- }
然而这样够吗?我们还应该想到一点,那就是空指针,也就是我们定义成类似这个样子的指针:
- vector<int> *p = 0;
对空指针的引用会不会出现问题呢。这个是可想而知了;故我们还应该对一层判断:
- if ( !p && !p->empty() && (*)p[1] == 1)
- {
- //do something ..
- }
这样就应该OK,完美了吧。呵呵。。说实话其实我们仅仅用最后一个条件进行判断一般也不会出错,因为我们使用的一般都是定义过的,且有内容的变量。但那样的程序强壮性与可维护性都可差。不是嘛?
既然这里牵涉到了!p 的用法,我是有必要说一下在条件判断中!p 和 *p == 0的区别了:
!p 是用来判断指针所指的对象是否为空,而*p 是来判断p所指的内容是否为0值。它们两个的区别在与:
① 对于所有类型的对象!p 均可以这样写出这样的形式,而*p == 0;就不一定了,它要看它所指的对象是否定义了== 这样的操作符重载,是否可以和 0 进行比较。
② 它们所进行的目的不同,一个是判断对象,一个是判断值,如:
- int *p = 0;
- if (*p == 0)
- {
- // do something...
- }
这样使用就会出错。正如我们上面所说的那样,我们还应加上一个 !p 的条件更合理。看下面情况:
- int value = 6;
- int *p = &value;
- if ( !p )
- {
- //do something....
- }
对于此例我们的目的若是想判断p所指向的值是否为0,那我们可惨了,条件永远满足,即使你修改过p所指向的值后再判断,条件依然满足。上面我们的行为是在判断是真所指向的对象是否是空对象。显然不是,故条件永远成立。若不知道这点的话,那我们的调试功夫可得多下一翻了。。呵呵。。
3 一些控制符
setfill(c) 设置填充字符
setw(t) 设置字符宽度,若宽度小于所设置的宽度,左补空格,若大于,则原样输出.
setprecision(n) 设置有效数字
setbase(int _Base);
If _Base is 8, then mask is ios_base::oct.