web-dev-qa-db-ja.com

ポストインクリメントとプレインクリメントのコンセプトは?

接尾辞と接頭辞の増分または減分の概念がわかりません。誰でもより良い説明をすることができますか?

64
Saad Masood

これまでの4つの答えはすべて、特定のイベントの順序を主張するという点で不正解です。

「都市伝説」は、多くの初心者(および専門家)が、表現における未定義の振る舞いに関する無限の質問の流れに惑わされていると信じていました。

そう。

組み込みのC++プレフィックス演算子の場合、

++x

xをインクリメントし、(式の結果として)xを左辺値として生成します。

x++

xをインクリメントし、(式の結果として)xの元の値を生成します。

特に、x++xの元の値の増分と生成に対して暗黙の時間順序付けはありません。コンパイラは、xの元の値を生成するマシンコードを自由に生成できます。それは何らかのレジスターに存在する可能性があり、それは式の終わり(次のシーケンスポイント)まで増分を遅らせます。

増分が最初に来なければならないと誤って信じる人々、そして彼らは多くの場合、実際には未定義の振る舞いを持っているのに特定の表現が明確に定義された効果を持たなければならないと結論づけます。

107
int i, x;

i = 2;
x = ++i;
// now i = 3, x = 3

i = 2;
x = i++; 
// now i = 3, x = 2

「ポスト」は後を意味します-つまり、変数が読み取られた後に増分が行われます。 「Pre」は前を意味します。したがって、変数値が最初に増分され、次に式で使用されます。

27
sje397

誰も質問に答えていません:なぜこの概念は混乱するのですか?

学部のコンピューターサイエンス専攻であるため、読み方コードのため、これを理解するのに時間がかかりました。

以下は正しくありません!


x = y ++

Xはyと等しいpost increment。これは、論理的には、XがYの値に等しいことを意味すると思われます-インクリメント操作が行われます。 投稿意味

または

x = ++ y
Xはyと等しいpre-increment。これは、論理的にはXがYの値に等しいことを意味しているように見えます-beforeインクリメント操作が行われます。 Pre意味before


実際に動作する方法は逆です。言語が誤解を招くため、この概念は混乱を招きます。この場合、動作を定義するために単語を使用することはできません。
x = ++ yは、XがYの値に等しいため、実際に読み取られます増分。
x = y ++は、XがYの値に等しいため、実際に読み取られますbefore増分。

Preとpostの単語は英語のセマンティクスに関して後方です。 ++がYの関係にあることのみを意味します。これ以上はありません。

個人的に、もし選択があれば、++ yとy ++の意味を切り替えます。これは、私が学ばなければならなかったイディオムの一例です。

この狂気への方法があれば、簡単な言葉で知りたい。

読んでくれてありがとう。

17
mathewbruens

postfix increment、x++prefix increment、++xの違いは、正確にはhowにあります2つの演算子がオペランドを評価します。後置インクリメントは、概念的にメモリ内のオペランドをコピーし、元のオペランドをインクリメントし、最終的にコピーの値を生成します。これは、コードで演算子を実装することで最もよく説明されると思います。

int operator ++ (int& n)  // postfix increment
{
    int tmp = n;
    n = n + 1;
    return tmp;
}

上記のコードは、プリミティブ型の演算子を再定義できないためコンパイルできません。コンパイラは、ここでprefixではなくpostfix演算子を定義していることを伝えることもできませんが、これが正しい有効なC++のふりをしましょう。後置演算子は実際にそのオペランドに作用することがわかりますが、インクリメント前の古い値を返すため、式x++の結果はインクリメント前の値になります。 xただし、isはインクリメントされます。

接頭辞の増分もそのオペランドを増分しますが、オペランドの値を生成しますafter増分:

int& operator ++ (int& n)
{
    n = n + 1;
    return n;
}

これは、式++xxafterの値に評価されることを意味します。

したがって、式++xはassignmnet (x=x+1)と同等であると考えるのは簡単です。ただし、incrementは異なるコンテキストで異なることを意味する可能性がある操作であるため、これは正確ではありません。単純なプリミティブ整数の場合、実際には++x(x=x+1)の代わりになります。しかし、リンクリストのイテレータなどのクラスタイプの場合、イテレータのプレフィックスの増分は、「オブジェクトに1を追加する」ことを意味するものではありません。

14
wilhelmtell

とても簡単です。どちらも変数の値をインクリメントします。次の2行は同じです。

x++;
++x;

違いは、インクリメントされる変数の値を使用している場合です。

x = y++;
x = ++y;

ここでは、両方の行がyの値を1増やします。ただし、最初のものはxに増分の前にyの値を割り当て、2番目はxに増分の後にyの値を割り当てます。

したがって、増分が式としても使用されている場合にのみ違いがあります。ポストインクリメントは、値を返した後にインクリメントします。事前増分は前に増分します。

6
Jonathan Wood
int i = 1;
int j = 1;

int k = i++; // post increment
int l = ++j; // pre increment

std::cout << k; // prints 1
std::cout << l; // prints 2

ポストインクリメントは、iに割り当てられた後にkの値がインクリメントされることを意味します。ただし、事前増分は、jがlに割り当てられる前に増分されることを意味します。

同じことが減分にも当てはまります。

4
Seth

ポストインクリメント(a ++)

Int b = a ++の場合、これは意味します

int b = a;

a = a+1;

ここで、値に1を追加します。値は、増分が行われる前に返されます。

たとえば、a = 1; b = a ++;

次に、b = 1およびa = 2

事前インクリメント(++ a)

Int b = ++ aの場合;それからこれは

a=a+1;

int b=a ;

事前インクリメント:これにより、メイン値に1が追加されます。値は、増分が行われた後に返されます。Fora = 1; b = ++ a;次に、b = 2およびa = 2です。

1
drvenom

次のステートメントでポストインクリメント(x ++)が発生します:

Post-increamentの例:

  static void Main(string[] args)
    {
        int x = 0;
        int y= Method(x++);//x=0
        Console.WriteLine(x);// now x=1
        Console.WriteLine(y);// but y=0;
    }
    public static int  Method(int x)
    {
       //when called value of x=0;
        return x;//returns 0

    }

Pre_increament(++ x)increamentは現在のステートメントで発生します

Pre-increamentの例:

  static void Main(string[] args)
    {
        int x = 0;
        int y= Method(++x);//x=1
        Console.WriteLine(x);// now also  x=1
        Console.WriteLine(y);//y is 1
    }
    public static int  Method(int x)
    {

       //inside x=1;
        return x; //returns 1

    }
0
venkat

インラインjavascriptスニペットがあるので、preおよびposインクリメントのインタラクティブな例を追加することもできます。 C++ではありませんが、コンセプトは変わりません。

let A = 1;
let B = 1;

console.log('A++ === 2', A++ === 2);
console.log('++B === 2', ++B === 2);
0
Olian04

C99標準から(奇妙なオーバーロードを除いて、C++は同じでなければなりません)

6.5.2.4後置インクリメントおよびデクリメント演算子

制約

1後置インクリメントまたはデクリメント演算子のオペランドは、修飾または非修飾の実数型またはポインター型を持ち、修正可能な左辺値でなければなりません。

セマンティクス

2後置++演算子の結果は、オペランドの値です。結果が取得された後、オペランドの値がインクリメントされます。 (つまり、適切なタイプの値1が追加されます。)制約、タイプ、変換、およびポインターに対する操作の影響に関する情報については、加法演算子と複合代入の説明を参照してください。オペランドの保存値を更新する副作用は、前のシーケンスポイントと次のシーケンスポイントの間に発生します。

3後置-演算子は、後置++演算子に似ていますが、オペランドの値が減らされる(つまり、適切なタイプの値1が減算される)ことを除きます。

6.5.3.1プレフィックスのインクリメントおよびデクリメント演算子

制約

1接頭辞の増分演算子または減分演算子のオペランドは、修飾または非修飾の実数型またはポインター型であり、変更可能な左辺値でなければなりません。

セマンティクス

2プレフィックス++演算子のオペランドの値がインクリメントされます。結果は、インクリメント後のオペランドの新しい値です。式++ Eは(E + = 1)と同等です。制約、型、副作用、変換、およびポインターに対する操作の効果については、加算演算子と複合代入の説明を参照してください。

3プレフィックス-演算子は、プレフィックス++演算子に似ていますが、オペランドの値が減らされる点が異なります。

0
Scott Wales