C 自增自減運算子過載int引數的問題

2021-08-20 18:19:06 字數 2481 閱讀 4570

解決為什麼自增自減運算子過載帶int引數就是後置,不帶就是前置的疑問

**:很久以前(八十年代),沒有辦法區分++和--操作符的字首與字尾呼叫。這個問題遭到程式設計師的報怨,於是c++語言得到了擴充套件,允許過載increment 和 decrement操作符的兩種形式。

然而有乙個句法上的問題,過載函式間的區別決定於它們的引數型別上的差異,但是不論是increment或decrement的字首還是字尾都只有乙個引數。為了解決這個語言問題,c++規定字尾形式有乙個int型別引數,當函式被呼叫時,編譯器傳遞乙個0做為int引數的值給該函式:

class upint ;

upint i;

++i; // 呼叫 i.operator++();

i++; // 呼叫 i.operator++(0);

--i; // 呼叫 i.operator--();

i--; // 呼叫 i.operator--(0);

這個規範有一些古怪,不過你會習慣的。而尤其要注意的是這些操作符字首與字尾形式返回值型別是不同的。字首形式返回乙個引用,字尾形式返回乙個const型別。下面我們將討論++操作符的字首與字尾形式,這些說明也同樣使用與--操作符。

從你開始做c程式設計師那天開始,你就記住increment的字首形式有時叫做「增加然後取回」,字尾形式叫做「取回然後增加」。這兩句話非常重要,因為它們是increment字首與字尾的形式上的規範。

// 字首形式:增加然後取回值

upint& upint::operator++()

// postfix form: fetch and increment

const upint upint::operator++(int)

字尾操作符函式沒有使用它的引數。它的引數只是用來區分字首與字尾函式呼叫。如果你沒有在函式裡使用引數,許多編譯器會顯示警告資訊,很令人討厭。為了避免這些警告資訊,一種經常使用的方法時省略掉你不想使用的引數名稱;如上所示。

很明顯乙個字尾increment必須返回乙個物件(它返回的是增加前的值),但是為什麼是const物件呢?假設不是const物件,下面的**就是正確的:

upint i;

i++++; // 兩次increment字尾

// 運算

這組**與下面的**相同:

i.operator++(0).operator++(0);

很明顯,第乙個呼叫的operator++函式返回的物件呼叫了第二個operator++函式。

有兩個理由導致我們應該厭惡上述這種做法,第一是與

內建型別行為不一致。當設計乙個類遇到問題時,乙個好的準則是使該類的行為與int型別一致。而int型別不允許連續進行兩次字尾increment:

int i;

i++++; // 錯誤!

第二個原因是使用兩次字尾increment所產生的結果與呼叫者期望的不一致。如上所示,第二次呼叫operator++改變的值是第一次呼叫返回物件的值,而不是原始物件的值。因此如果:

i++++;

是合法的,i將僅僅增加了一次。這與人的直覺相違背,使人迷惑(對於int型別和upint都是一樣),所以最好禁止這麼做。

c++禁止int型別這麼做,同時你也必須禁止你自己寫的類有這樣的行為。最容易的方法是讓字尾increment 返回const物件。當編譯器遇到這樣的**:

i++++; // same as i.operator++(0).operator++(0);

它發現從第乙個operator++函式返回的const物件又呼叫operator++函式,然而這個函式是乙個non-const成員函式,所以const物件不能呼叫這個函式。如果你原來想過讓乙個函式返回const物件沒有任何意義,現在你就知道有時還是有用的,字尾increment和decrement就是例子。(更多的例子參見effective c++ 條款21)

如果你很關心效率問題,當你第一次看到字尾increment函式時, 你可能覺得有些問題。這個函式必須建立乙個臨時物件以做為它的返回值,(參見條款19),上述實現**建立了乙個顯示的臨時物件(oldvalue),這個臨時物件必須被構造並在最後被結構。字首increment函式沒有這樣的臨時物件。由此得出乙個令人驚訝的結論,如果僅為了提高**效率,upint的呼叫者應該盡量使用字首increment,少用字尾increment,除非確實需要使用字尾increment。讓我們明確一下,當處理使用者定義的型別時,盡可能地使用字首increment,因為它的效率較高。

我們再觀察一下字尾與字首increment 操作符。它們除了返回值不同外,所完成的功能是一樣的,即值加一。簡而言之,它們被認為功能一樣。那麼你如何確保字尾increment和字首increment的行為一致呢?當不同的程式設計師去維護和公升級**時,有什麼能保證它們不會產生差異?除非你遵守上述**裡的原則,這才能得到確保。這個原則是字尾increment和decrement應該根據它們的字首形式來實現。你僅僅需要維護字首版本,因為字尾形式自動與字首形式的行為一致。

正如你所看到的,掌握字首和字尾increment和decrement是容易的。一旦了解了他們正確的返回值型別以及字尾操作符應該以字首操作符為基礎來實現的規則,就足夠了。

自增 自減運算子的過載

自增運算子 自減運算子 有前置 後置之分,為了區分所過載的是前置運算子還是後置運算子,c 規定 前置運算子作為一元運算子過載 過載為成員函式時 t operator t operator 過載為全域性函式時 t operator t t operatot t 後置運算子作為二元運算子過載,多寫乙個沒...

自增自減運算子

自增自減運算子 i 先使用i,然後i i 1 i 先使用i,然後i i 1 i 先i i 1然後使用i i 先i i 1 然後使用i 以下使用vc下除錯的結果,不同的編譯器可能有不同的結果。i 3 例1printf d i 結果輸出4 例2printf d i 結果輸出3 例3printf resu...

自增 ,自減 運算子

自增1運算子記為 其功能是使變數的值自增1。自減1運算子記為 其功能是使變數值自減1。自增1,自減1運算子均為單目運算,都具有右結合性。可有以下幾種形式 i i自增1後再參與其它運算。i i自減1後再參與其它運算。i i參與運算後,i的值再自增1。i i參與運算後,i的值再自減1。在理解和使用上容易...