1、C++中允许++ 和-- 操作符的前置和后置两种形式具有重载的能力。而重载是以参数类型来区分的,然而不论是++ 还是 -- 的前置或后置均没有参数,为了区分这两种不同的操作,只好让后置式有一个int自变量,并且在它调用的时候,编译器默认给该int指定一个0值。
例:
class Char
{
public:
Char& operator++ (); //前置式++,返回类型:引用
const Char operator++ (int); //后置式++,返回类型:const临时对象
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);
2、前置式返回调用它的对象的引用:后置式返回const 临时对象:
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的值也只是加了一次而已。这违反了我们的直觉,也违背了我们的意图,因此应该被禁止!
(c++中有一条原则就是“绝对不让用户更改临时对象”(异常处理除外),因为临时对象是由编译器产生的,我们无法主动使用,同时它的生存期也无法由我们来掌握,所以除了用临时对象来充当传入参数或返回值的"载体"外,任何对临时对象的更改都是无意义的,也就被编译器严厉禁止。)
让后置式返回const对象,可禁止上述行为。
i++++;//视同i.operator++(0).operator++(0);
第一次调用operator++返回的const对象,将被用来进行operator++的第二次调用。而const对象不能调用非常量成员函数,故无法调用。
3、由于后自增要创建一个临时对象保存之前对象的副本,所以比前自增效率要低,在两者效果相同的情况下推荐使用前自增。
前置式和后置式,它们除了返回值不同,完成的任务是相同的:将某值累加!如果只需进行累加,使用前置式的效率要比后置式的高,原因有两点:
- 后置式++调用了前置式++的操作;
- 后置式要生成一个临时对象存储原值,这中间有拷贝构造和析构的代价,而前置式却没有。
因此,应该尽可能使用前置式操作!