接尾辞と接頭辞のインクリメントまたはデクリメントの概念がわかりません。誰かがより良い説明をすることができますか?
13 に答える
これまでの 4 つの回答はすべて、イベントの特定の順序を主張するという点で正しくありません。
「都市伝説」が多くの初心者 (および専門家) を迷わせていると信じているため、つまり、表現における未定義の動作に関する果てしない質問の流れがあります。
そう。
組み込みの C++ プレフィックス演算子の場合、
++x
x
(式の結果x
として) 左辺値としてインクリメントおよび生成しますが、
x++
の元の値をインクリメントx
して (式の結果として) 生成しますx
。
特に、の元の値の増分と生成に暗示される時間順序x++
がないためです。コンパイラは、 の元の値を生成するマシン コードを自由に出力できます。たとえば、値が何らかのレジスタに存在し、式の最後 (次のシーケンス ポイント) までインクリメントを遅らせます。x
x
増分が最初に来なければならないと誤って信じている人々は多く、実際には未定義の動作がある場合でも、特定の式には明確に定義された効果が必要であると結論付けることがよくあります。
int i, x;
i = 2;
x = ++i;
// now i = 3, x = 3
i = 2;
x = i++;
// now i = 3, x = 2
「Post」は後を意味します。つまり、変数が読み取られた後にインクリメントが行われます。「前」は前を意味するため、変数値は最初にインクリメントされ、次に式で使用されます。
後置インクリメントx++
と前置インクリメントの違いは、2 つの演算子がオペランドを評価する方法にあり++x
ます。後置インクリメントは概念的にオペランドをメモリにコピーし、元のオペランドをインクリメントして、最終的にコピーの値を生成します。これは、コードで演算子を実装することで最もよく説明できると思います。
int operator ++ (int& n) // postfix increment
{
int tmp = n;
n = n + 1;
return tmp;
}
プリミティブ型の演算子を再定義できないため、上記のコードはコンパイルされません。コンパイラは、ここでprefixではなく後置演算子を定義していることもわかりませんが、これが正しく有効な C++ であると仮定しましょう。後置演算子が実際にそのオペランドに作用することがわかりますが、インクリメント前の古い値を返すため、式の結果はインクリメント前の値になります。ただし、インクリメントされます。x++
x
プレフィックスのインクリメントもオペランドをインクリメントしますが、インクリメント後のオペランドの値を生成します。
int& operator ++ (int& n)
{
n = n + 1;
return n;
}
これは、式がインクリメント後++x
の値に評価されることを意味します。x
したがって、この式++x
は assignmnet と同等であると考えるのは簡単(x=x+1)
です。ただし、これは正確にはそうではありません。インクリメントは、さまざまなコンテキストでさまざまなことを意味する可能性がある操作だからです。単純なプリミティブ整数の場合、実際に++x
は の代わりに使用でき(x=x+1)
ます。しかし、リンクされたリストの反復子などのクラス型の場合、反復子のプレフィックスのインクリメントは、「オブジェクトに 1 を追加する」ことを意味するものではありません。
誰もこの質問に答えていません: なぜこの概念は混乱を招くのですか?
コンピューター サイエンス専攻の学部生として、コードの読み方が原因で、これを理解するのにしばらく時間がかかりました。
以下は正しくありません!
x = y++
X は yポストインクリメントと同じです。これは論理的には、インクリメント操作が行われた後、 X が Y の値と等しいことを意味するように思われます。の後の投稿の意味。
また
x = ++y X は y pre
-increment
に等しい。これは論理的には、インクリメント操作が行われる前にX が Y の値と等しいことを意味するように思われます。前意味前。
その働き方は実は逆です。言葉が誤解を招くため、この概念は混乱を招きます。この場合、動作を定義するために単語を使用することはできません。x=++y は、X がインクリメント後
の Y の値に等しいため、実際には読み取られます。x=y++ は、X がインクリメント前
の Y の値に等しいため、実際には読み取られます。
pre と post という単語は、英語のセマンティクスに関して逆です。それらは、++ がリレーション Y のどこにあるかを意味するだけです。それ以上のことはありません。
個人的には、選択肢があれば、++y と y++ の意味を入れ替えます。これは、私が学ばなければならなかった慣用句のほんの一例です。
この狂気への方法があれば、簡単な言葉で知りたい.
読んでくれてありがとう。
とてもシンプルです。どちらも変数の値をインクリメントします。次の 2 行は同じです。
x++;
++x;
違いは、インクリメントされる変数の値を使用している場合です。
x = y++;
x = ++y;
ここでは、両方の行で y の値を 1 ずつ増やしています。ただし、最初のものはインクリメント前の y の値を x に割り当て、2 つ目はインクリメント後の y の値を x に割り当てます。
したがって、増分が式としても使用されている場合にのみ違いがあります。ポストインクリメントは、値を返した後にインクリメントします。pre-increment は前に増分します。
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
。
同じことがデクリメントにも当てはまります。
C99 標準から (奇妙なオーバーロードを除けば、C++ も同じはずです)
6.5.2.4 後置インクリメントおよびデクリメント演算子
制約
1 後置インクリメントまたはデクリメント演算子のオペランドは、修飾または非修飾の実数型またはポインター型を持ち、変更可能な左辺値でなければなりません。
セマンティクス
2 後置 ++ 演算子の結果は、オペランドの値です。結果が得られた後、オペランドの値がインクリメントされます。(つまり、適切な型の値 1 がそれに追加されます。) 制約、型、変換、およびポインターに対する操作の影響については、加算演算子と複合代入の説明を参照してください。オペランドの格納された値を更新する副作用は、前のシーケンス ポイントと次のシーケンス ポイントの間で発生します。
3 後置 -- 演算子は後置 ++ 演算子に似ていますが、オペランドの値が減分される (つまり、適切な型の値 1 がそこから減算される) 点が異なります。
6.5.3.1 前置インクリメントおよびデクリメント演算子
制約
1 前置インクリメントまたはデクリメント演算子のオペランドは、修飾または非修飾の実数型またはポインター型を持ち、変更可能な左辺値でなければなりません。
セマンティクス
2 前置 ++ 演算子のオペランドの値がインクリメントされます。結果は、インクリメント後のオペランドの新しい値です。式 ++E は (E+=1) と同等です。制約、型、副作用、変換、およびポインターに対する操作の影響については、加算演算子と複合代入の説明を参照してください。
3 前置 -- 演算子は前置 ++ 演算子に類似していますが、オペランドの値が減分されます。
前のインクリメントはインクリメント値の前です++
。
(++v) or 1 + v
ポストインクリメントは、値をインクリメントした後です++
。
(rmv++) or rmv + 1
プログラム:
int rmv = 10, vivek = 10;
cout << "rmv++ = " << rmv++ << endl; // the value is 10
cout << "++vivek = " << ++vivek; // the value is 11