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个改善编程与设计的有效方法 中文版》
posted @ 2012-04-16 16:27  hazir  阅读(3122)  评论(4编辑  收藏  举报

一个代码可以创造一个世界,也可以毁灭一个世界!