在C语言中我们学习了前置操作符和后置操作符,比如++i,--i,i++,i--,由于++和--属于同类型操作符,此处讲解均以++作为模型。
首先问一个问题,i++和++i有何区别?
i++就是先返回i的值然后再加1;++i则是先对i加1再返回i的值。这是一般的解释。
工程中,在C/C++中单独的两条语句在编译器编译后并没有任何区别,实现的汇编代码是一样的。
通过观察汇编代码发现确实没有什么区别,只有寄存器使用的不一样。
所以说,现代编译器会对代码进行优化使得最终的二进制程序更加高效,但是被优化后的代码失去了操作符原有的语义,不再可能从编译后的二进制程序还原成原先的C/C++代码,也就是说通过C/C++开发的软件无法完全反编译。
解释了普通类型的前置、后置操作符后我们想想能不能对他们也进行不改变语义的重载呢?要是可以的话又该如何进行区分?
同样的,++操作符也属于内置操作符,所以可以进行重载,并且全局函数和成员函数均可以进行重载,那么如何区分呢?重载前置++时不需要任何额外的参数;重载后置++操作符需要一个int类型的占位参数。重载过程如下:
Test& operator ++ ()
{
++mValue;
return *this;
}
Test operator ++ (int)
{
Test ret(mValue);
mValue++;
return ret;
}
前置++重载,根据前置++的原义,应该先是将变量值自增后并返回这个对象,所以需要返回引用。
后置++区别就大了一些,首先是声明形式上,它的返回类型不是一个引用,并且参数列表多了个int类型的占位参数用于区分,实现过程中使用了个局部对象,为什么使用局部对象?因为根据后置++的原生语义是先返回自身再对值进行自增,由于是重载函数,所以就需要一个临时对象保存当前对象,待变量值自增1后再返回这个临时对象,由于是局部变量,所以就不能返回引用。
所以,前置++操作符重载时效率更高,因为它不需要创建对象,不需要调用构造函数和析构函数,不需要占用空间。
如何使用?
Test t(0);
Test t1 = t++;
cout << t1.value() << endl;
Test t2 = ++t1;
cout << t2.value() << endl;
看看输出会是什么?
0
1
答案正是我们想要的,说明我们的重载是成功的。
所以我们可以真正回答文章开始的提问了,i++和++I有何区别?
对于基础类型的变量来说,前置++与后置++的效率基本相同,因为可能会经过编译器的优化。
对于类类型的变量来说,前置++的效率高于后置++的效率,所以我们应该尽可能使用前置++来提高程序运行效率。