class UPInt // "unlimited precision int"
{
public:
UPInt& operator++(); // ++ 前缀
const UPInt operator++(int); // ++ 后缀
UPInt& operator--(); // -- 前缀
const UPInt operator--(int); // -- 后缀
UPInt& operator+=(int); // += 操作符,UPInts
// 与ints 相运算
};
说明:不论是increment或decrement的前缀还是后缀都只有一个参数。为了解决这个语言问题,C++规定后缀形式有一个int类型参数,当函数被调用时,编译器传递一个0做为int参数的值给该函数。
前置与后置的区别
从声明上来看,函数返回值不一样,具体原因是由其语义决定的。
前缀形式:增加然后取回值
后缀形式: 取回然后增加
// 前缀形式:增加然后取回值
UPInt& UPInt::operator++()
{
*this += 1; // 增加
return *this; // 取回值
}
// 后缀形式: 取回然后增加
const UPInt UPInt::operator++(int)
{
UPInt oldValue = *this; // 取回值
++(*this); // 增加
return oldValue; // 返回被取回的值
}
说明1:前置与后置除了返回值不同外,所完成的功能是一样的,即值加一。那么当不同的程序员去维护和升级代码时,有什么能保证它们不会产生差异?除非你遵守上述代码里的原则,这才能得到确保。这个原则是后缀increment和decrement应该根据它们的前缀形式来实现。这样仅仅需要维护前缀版本,因为后缀形式自动与前缀形式的行为一致。
说明2:返回值,返回引用前提是对象已经必须存在,如此效率更高。但不能一味追求效率而返回引用类型,有些情况下返回的对象是临时创建的而不是已经存在。
说明3:后置形式的实现代码中可以看到,类对象有一个拷贝构造过程,这样势必影响效率。推论是UPInt的调用者应该尽量使用前缀increment,少用后缀increment,除非确实需要使用后缀increment。让我们明确一下,当处理用户定义的类型或迭代器或其他模板对象使用前置自增(对象的拷贝构造消耗时间相对久),因为它的效率较高。
说明4:后置形式的返回值const
那是为了避免以下的代码合法:UPInt i;i++++; 原因很简单,首先,int i;i++++;不合法!我们自定义的类应该要尽量靠近内置类型的行为!
其次,int i=1;i++++;结果是2,不是3,这与期待的结果不一致。