先加后加,
孰优孰劣?
—— ++i 和 i++ 比较
○
熟悉C语言或者C++语言的人都知道,运算符中有个++和--的操作,既可以放到变量前面,也可以放到变量后面,而且在绝大部分情况下,两者的结果是一样的。那么它们到底是不是完全一样呢?如果不一样的话,具体在什么方面会不一样呢?本文以++为例,但结论同样适用于--操作。
PART 01
对 i 值的影响
首先,前++和后++在任何情况下,对i的运行结果都是一样的。比如,设 int i=5,那么下列两行代码执行后,i 的值都是6:
++i;
i++;
以上两个操作都等价于 i = i+1。
PART 02
返回值
______
++ --
我们知道,赋值操作是可以形成一个链的,也即你可以这样写:
a = b = c + 1;
执行的时候,是先执行b = c +1,再把执行的结果赋给 a。也就是说赋值操作是有返回值的。
++i 和 i++ 是特殊的赋值语句,所以也是有返回值的。跟其它赋值语句一样,它们既可以作为独立的一行执行,也可以作为表达式的一部分(算术表达式或者逻辑表达式)。当作为独立的一行执行时,它们的返回值是被丢弃掉的。当放在表达式里时,它们的返回值是有用的,要参与运算。
现在,本质的区别来了。++i的返回值,是返回加1以后的i,而 i++ 是返回加1之前的i。比如,假设现在 i 等于5,那么在执行下面两行代码后(不是先执行第一行,再执行第二行,是指两行分开来独立执行),a 和 b 的值是不一样的:
a = ++i;
b = i++;
a 的值是6,b 的值是5。
这个其实是很好记的,放在前面就是先加1(后返回),放在后面就是(先返回)后加1。
但是,当把这两个表达式放在判断条件里时,就要特别当心,即使是相当资深的程序员有时也会犯错。
我们来看个例子:
int i = -1;
char s[27];
s[26] = 0;
while(i++<25)
s[i] = i + ‘A’;
puts(s);
当这段代码执行完毕后,如果你不再使用 i 了,那没关系。如果你还想继续使用 i,那么就要好好考虑 i 现在的值了。一般人会认为,i等于25时,循环的判断结果为假,循环退出,所以现在 i 的值就是25。但是,再思考一下,i++ 是先返回再加1 的,这个加1的动作跟判断的结果为真还是为假没有关系(只有循环体里的执行语句才会受到判断结果的影响),只要判断这个动作发生了,i 加1就一定会发生,所以现在 i 的值是26。这几乎有点颠覆你的认知了,但结果就是这样。
要避免误用 i 的值,最好在再次使用 i 前给 i 重新赋值。当然,最彻底的方法是,不要在条件判断里使用这种简写的方式。
(这种在判断条件里简写的方式还有一个缺点。由于 i 加1是在给数组赋值之前发生的,为了第一次循环是给第0个元素赋值,i 的初始值要设成-1,或者在给数组赋值前,把 i 先减1,两种做法都是很不直观的。)
PART 03
效率
如果你没有看过Scott Meyers的《More Effective C++》,那你一定不认为这两种写法会有效率上的差异,但不幸的是,两种方式的效率是有差异的。++i 要比 i++ 效率高,因为后者的内部实现调用了前者。大家知道,函数调用是要有开销的,多一次函数调用,效率就低一点。
More
Effective
C++
那么,为什么i++ 实现要调用++i呢?这就再次关系到这两个表达式的返回值。我们说i++ 是先返回 i 的值,然后再给 i 加1,实际代码中是没法先返回的,返回了函数就结束了,后面的操作不能被执行了。必须要把 i 的值先赋给另外一个变量,然后给 i 加1,然后再返回那个变量。i++ 的实现差不多是这样的:
int PostPlusPlus(int *i)
{
int j = *i;
++(*i);
return j;
}
由此你就明白了,为什么 ++i 要比 i++ 效率高。
PART 04
何去何从
那么在实际使用中,我们到底应该选择哪一个呢?答案是看场合。
如果是上层应用,而且不是在一个需要反复执行的循环里,那么两个都可以。因为现在硬件速度已经很快了,对于上层应用,根本不在乎这点效率的差别。
如果是在底层应用,或者在一个需要反复执行的循环里,那么就要考虑效率的问题。底层应用可能会被频繁地调用,即使一次调用只差十万分之一秒,多次反复调用就会有明显的差别。
如果是在条件判断表达式里,那么,还是不要用吧,除非你有十足的把握能够驾驭它。
总结:前++和后++,看起来很像,但还是有些细微的差别。明白了这些差别,当代码出错时,你就知道是怎么造成的了。
本文的结论同样适用于前--和后--。
如果你要了解更深入的分析,建议你看下Scott Meyers的《More Effective C++》,里边有更精彩的内容,比如谈到了++++的情形。
好了,今天的分享就到这里。大家一起来学编程,每天进步一点点!
i++
【盛格塾】
正心诚意,格物致知
以人文情怀审视软件,以软件技术改变人生
格友公众号
盛格塾小程序
扫描上方二维码或在微信中搜索“盛格塾”小程序
可以阅读更多文章和有声读物
往期推荐