最近虽然比较忙,也有点压力,不过相对还是闲的时间多,花了些时间看了些书。
还是感觉要写点什么,就从这里开始吧。
写在前面:--i和i-- 与 ++i和i++ 相似,这里仅讨论后者。
一、对于内置型数据
例如常见的int类型。++i和i++都是将i值自增1,不过++i表达式的值为自增后的值,i++的值为i原值,在之后才会自增。例子如下:
int i = 0;
int a = i++;
int b = ++i;
cout << a << b << endl;
再例如:
int i = 0;
int c = (++i)+(i++)+(++i)+(i++);
cout << c << i <<endl;
这里,2次++i 使得i值变为2,所以c=2+2+2+2;而i的值在 int c = (++i)+(i++)+(++i)+(i++) 之后再增加2变为4。
还有一点,++++i是合法的,而i++++是非法的。这点后面再讨论。
二、对于用户自定义类型
自定义类型就是我们常用的class。
如果有一个Test 类。声明如下:
class Test
{
... // 细节省略
};
先看看class Test类的++操作符的原型:
//<span style="font-size:18px;">
Test & operator++() // 前缀式{ *this+=1; // 重载过 operator += return *this;}</span>
//<span style="font-size:18px;">
const Test operator++(int) //后缀式{ Test T=*this; // 保留原值 ++(*this) // 重载过 operator++() return T;}</span>
先说明一点,上述两个声明这么做的原因是为了符合内置类型int的行为(以此为参考而设计)。其实完全可以不用这样,不过后果是可能达不到预期效果,当然如果喜欢或者特殊用途可以不像上面这样做。
++i为称为前缀表达式,i++称为后缀表达式。因为都是单目运算符,在重载时为了区分,后缀表达式参数中会有一个int参数。这个参数的作用仅仅是告诉编译器这是后缀表达式。并且在大多数编译器中其默认值为0。
对于前缀式返回引用,应该没什么疑问,这样不会产生额外的副本。应该说天生体质较好。而后缀式返回
const Test型是为了杜绝i++++的情景,这与内置int型行为不符。int为什么静止这么做是有原因的。如果把后缀式中
的const 去掉。i++++是在第一个++后的副本上再执行++,与预期结果并不符合。其实i++++如果显示调用就是:
i.operator++(0).operator(0)。const Test 可以有效的静止这一行为。
++++i则不同,返回值为Test& ,完全可以这么做,并且有预期效果。只能说在最初设计时天生体质好。
三、效率
对于内置类型,两者并无明显区别,甚至没有区别(编译器优化)。
对于自定义类型,++i的开销会小很多。
如果有错误和遗漏之处,欢迎指出。