【C++基础】第二十四课:递增和递减运算符

递增和递减运算符

Posted by x-jeff on May 20, 2021

【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);//如果先求右侧的值

也可能采取别的什么方式处理它。