近日在教學過程當中,遇到了一個比較有意思的代碼:微信
int main(){函數
int i = 0;this
i = i++;對象
//問若是打印i的值,結果是多少?編譯器
return 0;編譯
}class
這個問題實際上涉及到了前置及後置操做符的內部實現問題。關於深刻語言的底層彙編實現機制, 原理
下面咱們經過模仿前置和後置操做符的實現方式,來加深對前置、後置操做符實現原理的理解:引用
首先,咱們使用類MyInt來模擬整型:微信公衆號
class 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 <.......>
#include "MyInt.h"
int main(){
MyInt i = 0; //調用帶參構造
++i; //調用 i.operator++() i的值爲1
i++; //調用 i.operator++(0) i的值爲2
return 0;
}
從上面的結果看,都是實現了值的自增1
回到開始的問題:(使用咱們模擬實現的類)
int main(){
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,即
void main(){
//一、i = i++;
//二、i.operator+=(i.operator++(0));
//三、i.operator+=(0) -> i += 0
//四、i = 0
}
i = i++ 運行的結果就爲0。
更多幹貨筆記關注微信公衆號 : 老九學堂