6. 区别increment/decrement操作符的前置(prefix)和后置(postfix)形式
C++中允许++ 和-- 操作符的前置和后置两种形式具有重载的能力。而重载是以参数类型来区分的,然而不论是++ 还是 -- 的前置或后置均没有参数,为了区分这两种不同的操作,只好让后置式有一个int自变量,并且在它调用的时候,编译器默认给该int指定一个0值。
下面的例子是使char型也能进行++ 和 -- 的运算:
class Char { public: Char(char); Char& operator++ (); //前置式++ const Char operator++ (int); //后置式++ Char& operator-- (); //前置式-- const Char operator-- (int); //后置式-- Char& operator+= (int); //+=操作符 //... } Char C = 'a'; ++C; //调用C.operator++(); C++; //调用C.operator++(int); --C; //调用C.operator--(); C--; //调用C.operator--(int);
注意上面前置式和后置式的返回值的不同,仅以++操作符进行阐述:
C语言中++的前置和后置的区别为:前置式先累加后取出(increment and fetch),后置式先取出后累加(fetch and increment)。我们进行重载时,尽量不改变原来的意义,看看两种操作的实现:
Char& Char::operator ++() { (*this) += 1; //increment return *this; //fetch } const Char Char::operator ++ (int) { Char oldValue = *this; //fetch ++(*this); //increment return oldValue; }
由上序代码就能很回答:
前置式为什么要返回对象的引用了,因为直接对原对象本身进行了累加并返回自身。
后置式为什么要返回一个const对象?首先返回值必须是一个对象,这是显然的,因为要返回累加前的对象;其次为什么是const对象呢?如果不是const对象会出现什么情况:
其一,违反了后置++的运算语法规则:C语言中不允许两次使用后置++操作符,即下面的操作是非法的:
int i;
i++++; //error! (但++++i是合法的)
如果我们返回不是const对象,意味着下面的操作编译器不会报错:
Char c;
c++++; //不会报错,调用的动作如下
//c.operator++(0).operator++(0);
其二,运算结果不符合我们的预期:假设允许返回是非const对象,那么其运算结果和我们期望的并不相同:
如上面的代码,第二次operator++ 改变的对象是第一个operator++ 返回的对象,而不是原对象。即经过c++++之后,c的值也只是加了一次而已。这违反了我们的直觉,也违背了我们的意图,因此应该被禁止!
到这里,++操作符的前置和后置应该比较清楚了,而--操作符完全类似。
最后,如果仔细观察前置式和后置式,它们除了返回值不同,完成的任务是相同的:将某值累加!如果我们只需要进行累加,很显然使用前置式的效率要比后置式的高,原因有两点:
- 后置式++调用了前置式++的操作;
- 后置式要生成一个临时对象存储原值,这中间有拷贝构造和析构的代价,而前置式却没有。
因此,应该尽可能使用前置式操作!
参考文献: 《More Effective C++ 35个改善编程与设计的有效方法 中文版》
邮箱:haifenglinying#yahoo.cn (#->@)
个人主页:www.hazirguo.com