|
最近遇到了一个比较有意思的代码: { int i = 0; i = i++; //问如果打印i的值,结果是多少? return 0; } 这个问题实际上涉及到了前置及后置操作符的内部实现问题。 下面我们通过模仿前置和后置操作符的实现方式,来加深对前置、后置操作符实现原理的理解: 首先,我们使用类MyInt来模拟整型: public: int value; //实际的value值 MyInt(int value){ //方便初始化:MyInt i = 0; this->value = value; } /** * 重写前置式++运算符(++i时会自动调用本函数) * @return 前置式运算会返回当前对象的引用 */ MyInt& operator++(){ *this += 1; //累加后取出 return *this; } /** * 重写后置式++运算符(i++时会自动调用本函数) * 注意:由于函数重载是以参数类型来区分的,而前置、后置运算又都没有参数。为了解决这个语言学上的漏洞,只好让后置式运算符有一个int类型的参数(调用时,编译器会默默地为这个int型参数指定0值) * @return 返回一个const类型的对象 */ const MyInt operator++(int){ MyInt oldValue = *this; //取出当前对象 ++(*this); //累加(调用上面的前置++的重载函数) return oldValue; //返回先前被取出的值 } /** * 重载运算符+=,方便赋值操作:*this += 1; */ MyInt& operator+=(int value){ this->value = this->value + value; return *this; } //MyInt &operator--(); //前置式--的实现与上面类似 //MyInt UPInt operator--(); //后置式--的实现与上面类似 }; 有了上面的代码,我们再来看main函数里的调用: #include "MyInt.h" int main() { MyInt i = 0; //调用带参构造 ++i; //调用 i.operator++() i的值为1 i++; //调用 i.operator++(0) i的值为2 return 0; } 从上面的结果看,都是实现了值的自增1 回到开始的问题:(使用我们模拟实现的类) { MyInt i = 0; i = i++; //问如果打印i的值,结果是多少? return 0; } 首先会调用i++,即 i.operator++(0),函数代码如下: * 重写后置式++运算符(i++时会自动调用本函数) * @return 返回一个const类型的对象 */ const MyInt operator++(int){ MyInt oldValue = *this; //注意:oldValue是*this的副本,不是引用 ++(*this); //这里累加的是*this对象,而不是oldValue return oldValue; //返回的oldValue值并没有变化,仍然是初值 } 所以,i.operater++(0)执行后,表达式就成了:i = 0,即 { //1、i = i++; //2、i.operator+=(i.operator++(0)); //3、i.operator+=(0) -> i += 0 //4、i = 0 } i = i++ 运行的结果就为0。 |
微信公众号
手机版