【C++基础】系列博客为参考《C++ Primer中文版(第5版)》(C++11标准)一书,自己所做的读书笔记。
本文为原创文章,未经本人允许,禁止转载。转载请注明出处。
1.前言
递增和递减运算符有两种形式:前置版本和后置版本。
- 前置版本:首先将运算对象加1(或减1),然后将改变后的对象作为求值结果。
- 后置版本:将运算对象加1(或减1),但是求值结果是运算对象改变之前那个值的副本。
1
2
3
int i=0,j;
j=++i;//j=1,i=1
j=i++;//j=1,i=2
这两种运算符必须作用于左值运算对象。前置版本将对象本身作为左值返回,后置版本则将对象原始值的副本作为右值返回。
建议:除非必须,否则不用递增递减运算符的后置版本。
前置版本的递增运算符避免了不必要的工作,它把值加1后直接返回改变了的运算对象。与之相比,后置版本需要将原始值存储下来以便于返回这个未修改的内容。如果我们不需要修改前的值,那么后置版本的操作就是一种浪费。
2.在一条语句中混用解引用和递增运算符
举个例子,可以使用后置的递增运算符来控制循环输出一个vector对象内容直至遇到(但不包括)第一个负值为止:
1
2
3
4
auto pbeg=v.begin();
//输出元素直至遇到第一个负值为止
while (pbeg!=v.end() && *beg>=0)
cout<<*pbeg++<<endl;//输出当前值并将pbeg向前移动一个元素
后置递增运算符的优先级高于解引用运算符,因此*pbeg++
等价于*(pbeg++)
。pbeg++
把pbeg
的值加1,然后返回pbeg
的初始值的副本作为其求值结果,此时解引用运算符的运算对象是pbeg
未增加之前的值。最终,这条语句输出pbeg
开始时指向的那个运算,并将指针向前移动一个位置。
3.运算对象可按任意顺序求值
1
2
3
//该循环的行为是未定义的!
while(beg!=s.end() && !isspace(*beg))
*beg=toupper(*beg++);//错误:该赋值语句未定义
上述代码问题在于:赋值运算符左右两端的运算对象都用到了beg
,并且右侧的运算对象还改变了beg
的值,所以该赋值语句是未定义的。编译器可能按照下面的任意一种思路处理该表达式:
1
2
*beg=toupper(*beg);//如果先求左侧的值
*(beg+1)=toupper(*beg);//如果先求右侧的值
也可能采取别的什么方式处理它。