自增(++)和自减(--)操作符为对象加1和减1操作提供了方便简短的实现方式.它们有前置或后置两种使用形式.到目前为止,我们已经使用过前自增操作,该操作使其操作数加1,操作结果是修改后(changed)的值.同理,前自减操作使其操作数减1.这两种操作符的后置形式同样对其操作数加1(或减1),但操作后产生操作数原来的、未修改的值作为表达式的结果:
int i=0,j;
j=++i;//j=1,i=1:prefix yields incremented value
j=i++;//j=1,i=2:postfix yields unincremented value
因为前置操作返回加1后的值,所以返回对象本身,这是左值.而后置操作返回的则是右值.(也就是说,前置自增是先自增,然后操作赋值之类的,而后置自增可以理解为先操作,再自增.)
--------------------------------------------------我是华丽的分割线------------------------------------------------------
建议:只有在必要时才使用后置操作符
有使用C语言背景的读者可能会觉得奇怪,为什么要在程序中使用前自增操作.道理很简单:因为前置操作需要做的工作更少,只需加1后返回加1后的结果即可.而后置操作则必须先保存操作数原来的值,以便返回未加1之前的值作为操作的结果.对于int型对象和指针,编译器可优化掉这项额外工作.但是对于更多的复杂迭代器类型,这种额外工作可能会花费更大的代价.因此,养成使用前置操作这个好习惯,就不必操心性能差异的问题.
---------------------------------------------------我是华丽的分割线-----------------------------------------------------
1.后置操作符返回未加1的值.
当我们希望在单个复合表达式中使用变量的当前值,然后再加1时,通常会使用后置的++和--操作:
vector<int> ivec; //empty vector
int cnt=10;
//add elements 10...1 to ivec
while(cnt>0)
ivec.push_back(cnt--); //int postfix decrement
这段程序使用了后置的--操作实现cnt减1.我们希望把cnt的值赋给vector对象的下一个元素,然后在下次迭代前cnt的值减1.如果在循环中使用前置操作,则是用cnt减1后的值创建ivec的新元素,结果是将9至0十个元素依次添加到ivec中.
2.在单个表达式中组合使用解引用和自增操作
下面的程序使用了一种非常通用的C++编程模式输出ivec的内容:
vector<int>::iterator iter=ivec.begin();
//prints 10 9 8...1
while(iter !=ivec.end())
cout<<*iter++<<endl; //iterator postfix increment
由于后自增操作的优先级高于解引用操作,因此*iter++等效于*(iter++).子表达式iter++使iter加1,然后返回iter原值的副本作为该表达式的结果.因此,解引用操作*的操作数是iter未加1前的副本.
这种用法的根据在于后自增操作返回其操作数原值(没有加1)的副本.如果返回的是加1后的值,则解引用该值将导致错误的结果:ivec的第一个元素没有输出,并企图对一个多余的元素进行解引用.
------------------------------------------------------------------------我是饥饿的分割线----------------------------------
小心:如果程序员对C++和C语言都不太熟悉,则常常会弄不清楚表达式*iter++的含义.
建议:简洁即是美
没有C语言基础的C++新手,时常会因精简的表达式而苦恼,特别是像*iter++这类令人困惑的表达式.有经验的C++程序员非常重视简练,他们更喜欢这么写:
cout<<*iter++<<endl;
而不采用下面这种冗长的等效代码:
cout<<*iter<<endl;
++iter;
对于初学C++的程序员来说,第二种形式更清晰,因为给迭代器加1和获取输出值这两个操作是分开来实现的.但是更多的C++程序员更习惯使用第一种形式.
要不断地研究类似的代码,最后达到一目了然的地步.大部分的C++程序员更喜欢使用简洁的表达式而非冗长的等效表达式.因此,C++程序员必须熟悉这种用法.而且,一旦熟悉了这类表达式,我们会发现使用起来更不容易出错.
----------------------------------------------------我是饥饿的分割线---------------------------------------------------
习题5.15 解释前自增操作和后自增操作的差别.
前自增操作和后自增操作都使其操作数加1,二者的差别在于:前自增操作将修改后操作数的值作为表达式的结果值;而后自增操作将操作数原来的、未修改的值作为表达式的结果值
习题5.16 你认为为什么C++不叫做++C?
C++之名是Rick Mascitti在1983年夏天定名的,C说明它本质上是从C语言演化而来的,"++"是C语言的自增操作符.C||语言是C语言的超集,是在C语言基础上进行的扩展(引入了new、delete等C语言中没有的操作符,增加了对面向对象程序设计的直接支持,等等),是先有C语言,再进行++,根据自增操作符前、后置形式的差别,C++表示对C语言进行扩展之后,还可以使用C语言的内容;而写成++C则表示无法再使用C的原始值了,也就是说C++不能向下兼容C了,这与实际情况不符.
习题5.17 如果输出vector内容的while循环使用前自增操作符,那会怎么样?
如果返回的是加1后的值,则解引用该值将导致错误的结果:ivec的第一个元素没有输出,并企图对一个多余的元素进行解引用
随便黏贴一段程序:
#include<iostream>
using namespace std;
void reset(int *ip)
{
*ip=0;
ip=NULL;
}
void main()
{
int i=42;
int *p=&i;
cout<<"i:"<<*p<<'/n';
reset(p);
cout<<"i:"<<*p<<endl;
p=NULL;
cout<<"i:"<<*p<<endl;
}