- 下面的代碼有沒有區別?爲何?
void code() { int i = 0; i++; // i 的值做爲返回值, i 自增 1 ++i; // i 自增 1, i 做爲返回值 }
#include <iostream> using namespace std; int main() { int i = 0; i++; ++i; return 0; }
vc++ 2010 彙編ios
int i = 0; 0127136E mov dword ptr [i],0 i++; 01271375 mov eax,dword ptr [i] 01271378 add eax,1 0127137B mov dword ptr [i],eax ++i; 0127137E mov eax,dword ptr [i] 01271381 add eax,1 01271384 mov dword ptr [i],eax
g++ 彙編c++
14 int i = 0; 0804869d: movl $0x0,0x1c(%esp) 16 i++; 080486a5: addl $0x1,0x1c(%esp) 18 ++i; 080486aa: addl $0x1,0x1c(%esp)
對於基礎數據類型,在工程上沒有任何區別。
因爲實例中沒有使用返回值,通過編譯器優化後,生成相同的彙編代碼。編程
- 現代編譯器產品會對代碼進行優化
- 優化使得最終的二進制程序更高效
- 優化後的二進制程序失去了 C/C++ 的原生語義
- 不可能從編譯後的二進制程序徹底還原 C/C++ 程序
C/C++ 開發的軟件沒法徹底反編譯函數
思考:
++ 操做符能夠重載嗎?如何區分前置 ++ 和後置 ++?優化
++ 操做符能夠被重載this
- 全局函數和成員函數都可進行重載【推薦成員函數】
- 重載前置 ++ 操做符不須要額外的參數
- 重載後置 ++ 操做符須要一個 int 類型的佔位參數
#include <iostream> using namespace std; class Test { private: int mValue; public: Test(int i) { mValue = i; } int value() { return mValue; } Test& operator ++ () { mValue = mValue + 1; return *this; } Test operator ++ (int) // 返回值而不是引用 { Test ret(mValue); mValue = mValue + 1; return ret; } }; int main() { Test t1(0); Test t2(0); Test tt1 = t1++; cout << t1.value() << endl; cout << tt1.value() << endl; Test tt2 = ++t2; cout << t2.value() << endl; cout << tt2.value() << endl; return 0; }
輸出: 1 0 1 1
後置 ++ 操做符重載分析:編碼
Test operator ++ (int) { Test ret(mValue); mValue = mValue + 1; return ret; }
對於基礎類型的變量spa
- 前置 ++ 的效率與後置 ++ 的效率基本相同
- 根據項目組編碼規範進行選擇
對於類類型的對象code
- 前置 ++ 的效率高於後置 ++
- 儘可能使用前置 ++ 操做符提升程序效率
Complex.h對象
#ifndef _COMPLEX_H_ #define _COMPLEX_H_ class Complex { private: double a; double b; public: Complex(int a = 0, int b = 0); int getA(); int getB(); int 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); Complex& operator -- (); Complex operator -- (int); }; #endif
Complex.cpp
#include "Complex.h" #include <math.h> Complex::Complex(int a, int b) { this->a = a; this->b = b; } int Complex::getA() { return a; } int Complex::getB() { return b; } int Complex::getModulus() { return sqrt(a * a + b * b); } Complex Complex::operator + (const Complex& c) { double na = a + c.a; double nb = b + c.a; 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 nm = c.a * c.a + c.b * c.b; double na = (a * c.a + b * c.b) / nm; double nb = (b * c.a - a * c.b) / nm; 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; } 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; }
main.cpp
#include <iostream> #include "Complex.h" using namespace std; int main() { Complex c1(0, 0); Complex c2(0, 0); Complex c3 = c1++; cout << c3.getA() << endl; cout << c3.getB() << endl; Complex c4 = ++c2; cout << c4.getA() << endl; cout << c4.getB() << endl; return 0; }
輸出: 0 0 1 1
- 編譯優化使得最終的可執行程序更加高效
- 前置 ++ 操做符和後置 ++ 操做符均可以被重載
- ++ 操做符的重載必須符合原生語義
- 對於基礎類型, 前置 ++ 與 後置 ++ 的效率幾乎相同
- 對於類類型,前置 ++ 的效率高於後置 ++
以上內容參考狄泰軟件學院系列課程,請你們保護原創!