簡體   English   中英

++什么時候不會產生與+1相同的結果?

[英]When does ++ not produce the same results as +1?

以下兩個C#代碼段產生不同的結果(假定在遞歸調用之前和之后都使用變量級別)。 為什么?

public DoStuff(int level)
{
  // ...
  DoStuff(level++);
  // ...
}

public DoStuff(int level)
{
  // ...
  DoStuff(level+1);
  // ...
}

閱讀下面的一些回答后,我認為值得發布有關level ++,++ level和level + 1的堆棧跟蹤信息,以突出說明如何欺騙此問題。

我為這篇文章簡化了它們。 遞歸調用序列以DoStuff(1)開始。

//級別++

DoStuff(int level = 1)
DoStuff(int level = 2)
DoStuff(int level = 2)
DoStuff(int level = 2)

// ++級

DoStuff(int level = 4)
DoStuff(int level = 4)
DoStuff(int level = 3)
DoStuff(int level = 2)

// +1級

DoStuff(int level = 4)
DoStuff(int level = 3)
DoStuff(int level = 2)
DoStuff(int level = 1)

為了闡明所有其他答復:

+++++++++++++++++++++

DoStuff(a++);

等效於:

DoStuff(a);
a = a + 1;

+++++++++++++++++++++

DoStuff(++a);

等效於:

a = a + 1;
DoStuff(a);

+++++++++++++++++++++

DoStuff(a + 1);

等效於:

b = a + 1;
DoStuff(b);

+++++++++++++++++++++

因為第一個示例實際上等效於:

public DoStuff(int level)
{  
  // ...
  int temp = level;
  level = level + 1;
  DoStuff(temp);
  // ...
}

注意,您也可以編寫++ level。 那等於:

public DoStuff(int level)
{  
  // ...
  level = level + 1;
  DoStuff(level);
  // ...
}

我認為最好不要過度使用++和-運算符; 它很快就會引起混亂和/或不確定實際發生的事情,並且現代C ++編譯器無論如何都不會使用這些運算符生成更有效的代碼。

level ++會將級別傳遞給DoStuff ,然后遞增級別以在其余函數中使用。 這可能是一個相當討厭的錯誤,因為遞歸將永遠不會結束(根據所示, DoStuff始終會傳遞相同的值)。 也許++ level是相反的意思,因為這與level ++相反(遞增level並將遞增的值傳遞給DoStuff )?

級別+1級別+1傳遞到DoStuff中 ,而其余​​部分的級別保持不變。

level++的返回值將是levelthereforelevel傳遞給DoStuff 這可能是一個非常討厭的錯誤,因為遞歸將永遠不會結束(根據所示, DoStuff始終以相同的值傳遞)。 也許++levellevel + 1是代替的?

level + 1將把level + 1傳遞到DoStuff ,而其余​​部分的level保持不變。


后增量運算符(variable ++)與該函數完全等效

int post_increment(ref int value)
{
    int temp = value;
    value = value + 1
    return temp;
}

而預增量運算符(++變量)恰好等於該函數

int pre_increment(ref int value)
{
    value = value + 1;
    return value;
}

因此,如果將內聯運算符擴展為代碼,則這些運算符等效於:

DoStuff(a + 1)

int temp = a + 1;
DoStuff(temp);

DoStuff(++a)

a = a + 1;
DoStuff(a);

DoStuff(a++);

int temp = a;
a = a + 1;
DoStuff(temp);

重要的是要注意,后增量等於:

DoStuff(a);
a = a + 1;

另外,作為一種風格,除非要使用遞增的值(規則的特定版本,“除非您打算使用該值,否則不要為變量賦值”),否則不應遞增值。 )。 如果不再使用值i + 1 ,則首選用法應該是DoStuff(i + 1)而不是DoStuff(++i)

首先是使用級別中的值,然后將其遞增。

后者使用level + 1作為傳遞變量。

level++返回的當前值level ,然后遞增level level+1根本不會改變level ,但是DoStuff的值是(level + 1)

public DoStuff(int level)
{

  // DoStuff(level);
  DoStuff(level++);
  // level = level + 1;
  // here, level's value is 1 greater than when it came in
}

它實際上增加了level的值。

public DoStuff(int level)
{
  // int iTmp = level + 1;
  // DoStuff(iTmp);
  DoStuff(level+1);
  // here, level's value hasn't changed
}

實際上並不會增加level的值。

在函數調用之前這不是一個大問題,但是在函數調用之后,值將有所不同。

在level ++中,您正在使用后綴運算符。 使用該變量后,該運算符將起作用。 也就是說,將其放入調用函數的堆棧后,它會遞增。 另一方面,+ 1是簡單的數學表達式,它被求值並將結果傳遞給被調用的函數。 如果要先遞增變量,然后將其傳遞給被調用的函數,則可以使用前綴運算符:++ level

第一個代碼段使用后操作增量運算符,因此調用以DoStuff(level);進行。 如果要在此處使用增量運算符,請使用DoStuff(++ level);。

級別+1將任何級別+1發送給該函數。 level ++將級別發送給函數,然后將其遞增。

您可以進行++級別的操作,這很可能會為您提供所需的結果。

第一個示例使用“索引”的值,增加值並更新 “索引”。

第二個示例使用“索引”的值加1,但不更改“索引”的內容。

因此,根據您想要在這里做什么,商店中可能會有一些驚喜!

雖然很誘人地將其重寫為:

DoStuff(++level);

我個人認為,這比在方法調用之前增加變量的可讀性差。 如上面的幾個答案所述,以下內容將更加清楚:

level++;
DoStuff(level);

當您使用允許運算符重載的語言時,已經定義了'+ <integer>'來執行除后綴和前綴++之外的其他操作。

再說一次,我只在學校項目中看到過這樣的可憎之處*,如果您在野外遇到這種情況,您可能有一個很好的,有據可查的理由。

[*一堆整數,如果我沒記錯的話。 按下並彈出“ ++”和“-”,而“ +”和“-”執行常規算術]

簡而言之, ++var是一個前綴運算符,它將在表達式的其余部分求值之前遞增變量。 后綴運算符var++在對表達式的其余部分求值之后對變量進行遞增。 當然,正如其他人提到的那樣, var+1只會創建一個臨時變量(在內存中是單獨的),該變量以var並以常數1遞增。

就我的經驗而言,參數表達式首先被求值,並獲得level的值。 變量本身在函數被調用之前就增加了,因為編譯器並不在乎您是否使用表達式作為參數……否則,它所知道的是它應該增加值並獲得舊值作為結果。表達。

但是在我看來,這樣的代碼確實很草率,因為通過嘗試變得聰明,它使您必須三思而后行。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM