-
在下面的代码有没有区别?为什么呢?
i++; //i的值作为返回值,i自增1 ++i; //i自增1,i的值作为返回值
-
观察反汇编文件,我们会发现一个问题:对于有些普通类型的变量的前置操作符和后置操作符的反汇编文件是一模一样的,由此可知,编译器对其进行了优化!
-
现代编译器产品会对代码进行优化
-
优化使得最终的二进制程序更加高效
-
优化后的二进制程序丢失了C/C++的原生语义
-
不可能从编译后的二进制程序还原C/C++程序
-
思考问题:++操作符可以重载吗?如何区分前置++和后置++?
-
++操作符可以被重载
-
全局函数和成员函数均可以进行重载
-
重载前置++操作符不需要额外的参数
-
重载后置++操作符需要一个int类型的占位参数
class Test { int mvalue; public: Test(int _value) { mvalue = _value; } int get_value() { return mvalue; } //重载++(前置)操作符 (前置++效率高点,因为没有生成额外的对象) Test& operator ++() { //【step1】先将当前对象的值加1 ++mvalue; //【step2】在返回当前对象 return *this; } //重载++(后置)操作符 Test operator ++(int) { //【step1】定义一个需要返回的对象,把当前对象的值保留下来 Test ret(mvalue); //【step2】将当前对象的值进行自增1操作 mvalue++; return ret; } };
-
真正的区别?
-
对于基础类型的变量,前置++的效率与后置++的效率基本相同,我们需要根据项目组编码规范进行选择
-
对于类类型的对象,前置++的效率高于后置++,尽量使用前置操作符来提高程序的效率
2 // 前置和后置操作符.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。 3 // 4 #include <iostream> 5 #include <string> 6 using namespace std; 7 class Test 8 { 9 int mvalue; 10 public: 11 Test(int _value) 12 { 13 mvalue = _value; 14 } 15 int get_value() 16 { 17 return mvalue; 18 } 19 //重载++(前置)操作符 (前置++效率高点,因为没有生成额外的对象) 20 Test& operator ++() 21 { 22 //【step1】先将当前对象的值加1 23 ++mvalue; 24 //【step2】在返回当前对象 25 return *this; 26 } 27 //重载++(后置)操作符 28 Test operator ++(int) 29 { 30 //【step1】定义一个需要返回的对象,把当前对象的值保留下来 31 Test ret(mvalue); 32 //【step2】将当前对象的值进行自增1操作 33 mvalue++; 34 return ret; 35 } 36 }; 37 int main() 38 { 39 int i = 0; 40 i++; 41 ++i; 42 #if 1 43 Test t(0); 44 cout << "t.mvalue=" << t.get_value() << endl; 45 Test tt = ++t; 46 cout << "t.mvalue=" << t.get_value() << endl; 47 cout << "tt.mvalue=" << tt.get_value() << endl; 48 tt = t++; 49 cout << "tt.mvalue=" << tt.get_value() << endl; 50 #endif 51 }
运行结果:
t.mvalue=0
t.mvalue=1
tt.mvalue=1
tt.mvalue=1
-
小结:
-
编译优化使得最终的可执行程序更加高效
-
前置++操作符和后置++操作符都可以被重载
-
++操作符的重载必须符合原生语义
-
对于基础类型,前置++与后置++的效率几乎相同
-
对于类类型,前置++的效率高于后置++