6.自增,自减操作符前置与后置的区别

前置与后置操作符

 
重载函数间的区别在于它们参数类型上的差异,但是无论increment还是decrement的前缀与后缀都只有一个参数。为了解决问题,c++规定后缀形式有一个int类型参数,当函数被调用时编译器传递一个0作为int参数的值:

1
2
3
4
5
6
7
8
9
10
11
class UPInt { //unlimited precision int
public:
UPInt& operator++();
const UPInt operator++(int);
UPInt& operator--();
const UPInt operator--(int);
...
};
UPInt i;
++i; //i.operator++();
i++; //i.operator++(0);

仔细观察可以发现,前缀返回的是引用,后缀返回的则是一个const对象。


具体实现

 
以自增为例,前缀表达的意思是“增加然后取出”,后缀表达的意思是“取出然后增加”,以下是具体实现:

1
2
3
4
5
6
7
8
9
UPInt& UPInt::operator++(){
*this += 1;
return *this;
}
const UPInt UPInt::operator++(int){
UPInt oldValue = *this;
++(*this);
return oldValue;
}


返回值

 
很明显一个后缀操作符必须返回一个对象,但是为什么必须是const对象呢?
假设返回值不是const 对象,下面的代码就是正确的:

1
2
UPInt i;
i++++;//i.operator++(0).operator++(0);

我们拒绝表达式编译通过,理由有二:

  1. 保证与内置类型具备行为一致
  2. 直觉上我们认为i++++应该自增2次,但实际上它只自增了一次,只有最后一个++生效

如果后缀返回const对象,那么第二个++由于是non-const成员函数,将无法通过编译。


效率

 
由于后缀操作符需要返回对象的原因(不可避免的构造与析构),前缀比后缀的效率要高,在用户自定义类型上更是明显,因此我们在能用前缀的时候应该使用前缀。