1 问题
-
下面的代码有没有区别?为什么?
- 在工程上没有区别,编译器进行了优化
i++; // i的值作为返回值,i自增1 ++i; // i自增1,i的值作为返回
-
示例1:
i++
和++i
的区别-
Demo
#include <iostream> #include <string> using namespace std; int main() { int i = 0; i++; ++i; return 0; }
-
VS 汇编代码:相同,只有使用的寄存器不同而已 => 在忽略返回值的情况下
#include <iostream> #include <string> using namespace std; int main() { 000E1C70 push ebp 000E1C71 mov ebp,esp 000E1C73 sub esp,0CCh 000E1C79 push ebx 000E1C7A push esi 000E1C7B push edi 000E1C7C lea edi,[ebp-0CCh] 000E1C82 mov ecx,33h 000E1C87 mov eax,0CCCCCCCCh 000E1C8C rep stos dword ptr es:[edi] 000E1C8E mov ecx,offset _2F191172_main@cpp (0EC02Ah) 000E1C93 call @__CheckForDebuggerJustMyCode@4 (0E128Fh) int i = 0; 000E1C98 mov dword ptr [i],0 //将0放到标识符i对应的4个字节的内存中 i++; 000E1C9F mov eax,dword ptr [i] //将标识符i所对应的内存中的值传到eax寄存器中 000E1CA2 add eax,1 //将eax寄存器中的值加1 000E1CA5 mov dword ptr [i],eax //将eax寄存器中的值传到标识符i所对应的内存中去 ++i; 000E1CA8 mov eax,dword ptr [i] 000E1CAB add eax,1 000E1CAE mov dword ptr [i],eax return 0; 000E1CB1 xor eax,eax } 000E1CB3 pop edi 000E1CB4 pop esi 000E1CB5 pop ebx 000E1CB6 add esp,0CCh 000E1CBC cmp ebp,esp 000E1CBE call __RTC_CheckEsp (0E1299h) 000E1CC3 mov esp,ebp 000E1CC5 pop ebp 000E1CC6 ret
-
-
分析
- 现代编译器会对代码进行优化
- 优化使得最早的二进制程序更加高效
- 优化后的二进制程序丢失了 C/C++ 的原生语义
- 不可能从编译后的二进制程序还原 C/C++ 程序
2 重载 ++ 操作符
-
【问题】
++
操作符可以重载么?如何区分前置++
和后置++
? -
++
操作符可以被重载- 全局函数和成员函数(推荐)均可进行重载
- 重载前置
++
操作符不需要额外的参数 - 重载后置
++
操作符需要一个int
类型的占位参数
-
实例2:
++
操作符的重载-
Demo
#include <iostream> #include <string> using namespace std; class Test { int mValue; public: Test(int i) { mValue = i; } int value() { return mValue; } // 成员函数进行前置++操作符重载,返回类引用,没有在栈上生成额外的对象 Test& operator ++ () { ++mValue; return *this; } // 成员函数进行后置++操作符重载,返回局部变量 Test operator ++ (int) { Test ret(mValue); // 在栈上创建对象,需要调用构造函数、析构函数 mValue++; return ret; } }; int main() { Test t(0); Test t1(0); cout << t.value() << endl; // 0 cout << t1.value() << endl; // 0 Test tt = t++; cout << t.value() << endl; // 1 cout << tt.value() << endl; // 0 Test tt1 = ++t1; cout << t1.value() << endl; // 1 cout << tt1.value() << endl; // 1 return 0; }
-
-
++
前置和后置真正的区别-
对于基础类型的变量
- 前置
++
的效率和后置++
的效率基本相同 - 根据项目组编码规范进行选择
- 前置
-
对于类类型的对象
- 前置
++
的效率高于后置++
:前置++
返回类引用,没有生成额外的对象,后置返回局部的类对象 - 尽量使用前置
++
操作符提高程序效率
- 前置
-
-
复数类
Complex
的进一步完善-
Demo
// Complex.h #ifndef COMPLEX_H_ #define _COMPLEX_H_ class Complex { double a; double b; public: Complex(double a = 0, double b = 0); double getA(); double getB(); double getModulus(); Complex operator + (const Complex& c); Complex operator - (const Complex& c); Complex operator * (const Complex& c); Complex operator / (const Complex& c); bool operator == (const Complex& c); bool operator != (const Complex& c); Complex& operator = (const Complex& c); // 重载++操作符 Complex& operator ++ (); Complex operator ++ (int); }; #endif //Complex.cpp #include <cmath> #include "Complex.h" Complex::Complex(double a, double b) { this->a = a; this->b = b; } double Complex::getA() { return a; } double Complex::getB() { return b; } double Complex::getModulus() { return sqrt(a * a + b * b); } Complex Complex::operator + (const Complex& c) { double na = a + c.a; double nb = b + c.b; Complex ret(na, nb); return ret; } Complex Complex::operator - (const Complex& c) { double na = a - c.a; double nb = b - c.b; Complex ret(na, nb); return ret; } Complex Complex::operator * (const Complex& c) { double na = a * c.a - b * c.b; double nb = a * c.b + b * c.a; Complex ret(na, nb); return ret; } Complex Complex::operator / (const Complex& c) { double cm = c.a * c.a + c.b * c.b; double na = (a * c.a + b * c.b) / cm; double nb = (b * c.a - a * c.b) / cm; Complex ret(na, nb); return ret; } bool Complex::operator == (const Complex& c) { return (a == c.a) && (b == c.b); } bool Complex::operator != (const Complex& c) { return !(*this == c); } Complex& Complex::operator = (const Complex& c) { if( this != &c ) { a = c.a; b = c.b; } return *this; } // 重载前置++操作符 Complex& Complex::operator ++ () { a = a + 1; b = b + 1; return *this; } // 重载后置++操作符 Complex Complex::operator ++ (int) { Complex ret(a, b); a = a + 1; b = b + 1; return ret; }
-
应用
#include <iostream> #include "Complex.h" using namespace std; int main() { Complex c(0,0); Complex b = ++c; Complex b1 = c++; cout << b.getA() << endl; // 1 cout << b.getB() << endl; // 1 cout << b1.getA() << endl; // 0 cout << b1.getB() << endl; // 0 return 0; }
-