<<More Effective C++>> 学习笔记【六】
这个议题首先讨论的是++和--操作符的重载,为了区分前缀和后缀形式,C++语言规定后缀形式有一个int类型参数,当函数被调用时,编译器传递一个0做为int参数的值给该函数。
class UPInt {
public:
UPInt& operator++(); // ++ 前缀
const UPInt operator++(int); // ++ 后缀
UPInt& operator--(); // -- 前缀
const UPInt operator--(int); // -- 后缀
UPInt& operator+=(int); // += 操作符,UPInts
// 与ints 相运算
};
调用过程中:
UPInt i;
++i; // 调用 i.operator++();
i++; // 调用 i.operator++(0);
--i; // 调用 i.operator--();
i--; // 调用 i.operator--(0);
后缀操作符函数
- 带一个int性参数,实参=0,但不会被使用。它的参数只是用来区分前缀与后缀函数调用。
- 返回一个const类型。
之所以后缀运算符是返回const型参数,原因在于避免两次自增操作,如果不是const的返回值,如下代码将会有意义:
UPInt i;
i++++; // 两次increment后缀,错误的语法!!
//等同于:
i.operator++(0).operator++(0); //错误的语法!!
这种做法不好的地方在于:
- 与内置类型行为不一致:
int类型连续自增是不允许的);
- 与期望的行为不一致:
注~函数返回const型对象的一个作用
当处理用户定义的类型时,尽可能地使用前缀increment,因为它的效率较高:
为了返回一个临时对象以做为它的返回值,后缀表达式往往需要建立一个临时对象,所以为了提高效率,针对用户定义类型,应该尽量考虑使用前缀自增自减表达式。
后缀increment和decrement应该根据它们的前缀形式来实现:
为了确保后缀increment和前缀increment的行为一致,同时为了保证修改的简便性,后缀式应该通过调用前缀形式来实现。
<<More Effective C++>> 中的示例实现为:
// 前缀形式:增加后取回
UPInt& UPInt::operator++()
{
*this += 1; // 增加
return *this; // 取回值
}
// 后缀形式:取回后增加
const UPInt UPInt::operator++(int)
{
UPInt oldValue = *this; // 取回值
++(*this); // 调用前缀式
return oldValue; // 返回被取回的值
}
总结要点:
- 对于后缀式自增自减运算符,返回值应该是常量,这样避免连续自增操作;
- 为了区分后缀式与前缀式自增自减运算符,需要增加一个int型参数,编译器会赋“0”,但是不需要写出参数名,以避免多数编译器的警告;
- 后缀式的实现应该依赖于前缀式的实现;
- 对用户定义类型尽量调用前缀式自增自减运算符,以节约资源;
- 重载后缀式自增自减运算符是函数返回const类型返回值的一个具体应用。