web-dev-qa-db-ja.com

「++」演算子と「+ = 1」演算子の違いは何ですか?

C++のループでは、通常++または+=1を使用する状況に遭遇しますが、それらの違いはわかりません。たとえば、整数がある場合

int num = 0;

そして、ループで:

num ++;

または

num += 1;

両方ともnumの値を増やしますが、それらの違いは何ですか? num++num+=1よりも高速に動作するのではないかと疑っていますが、どのようにすればよいですか?この違いは無視できるほど微妙ですか?

42
E_learner

num += 1++numとかなり同等です。

これらのすべての式(num += 1num++および++num)は、numの値を1つ増やしますが、num++の値はnum had beforeインクリメントされました。

図:

int a = 0;
int b = a++; // now b == 0 and a == 1
int c = ++a; // now c == 2 and a == 2
int d = (a += 1); // now d == 3 and a == 3

好きなものを使ってください。 ++numよりもnum += 1の方が好きです。

81
Alexandre C.

prefixおよびpostfix操作は、試験問題の完璧な候補です。

a = 0;
b = a++;  // use the value and then increment --> a: 1, b: 0

a = 0;
b = ++a;  // increment and then use the value --> a: 1, b: 1

+=操作とその姉妹-=は、主に異なる番号で使用することを目的としたより一般的なソリューションです。 1とともに使用すると冗長であるとさえ言うかもしれません。 1とともに使用すると、ほとんどの場合prefix操作として機能します。実際、私のマシンでは同じマシンコードを生成します。次のようなプログラム例を使用して、これを試すことができます。

void foo() {
    int a, b;
    a = 0;

    // use one of these four at a time
    b = a++;          // first case (different)
    b = ++a;          // second case
    b = (a += 1);     // third case
    b = (a = a + 1);  // fourth case
}

int main() {
    foo();
    return 0;
}

gdbで分解すると、次の結果が得られます。

最初のケース(a++)(異なる)

(gdb) disassemble foo
Dump of assembler code for function foo:
   0x00000000004004b4 <+0>:     Push   %rbp
   0x00000000004004b5 <+1>:     mov    %rsp,%rbp
   0x00000000004004b8 <+4>:     movl   $0x0,-0x8(%rbp)
   0x00000000004004bf <+11>:    mov    -0x8(%rbp),%eax
   0x00000000004004c2 <+14>:    mov    %eax,-0x4(%rbp)
   0x00000000004004c5 <+17>:    addl   $0x1,-0x8(%rbp)
   0x00000000004004c9 <+21>:    pop    %rbp
   0x00000000004004ca <+22>:    retq
End of assembler dump.

2番目のケース(++a

(gdb) disassemble foo
Dump of assembler code for function foo:
   0x00000000004004b4 <+0>:     Push   %rbp
   0x00000000004004b5 <+1>:     mov    %rsp,%rbp
   0x00000000004004b8 <+4>:     movl   $0x0,-0x8(%rbp)
   0x00000000004004bf <+11>:    addl   $0x1,-0x8(%rbp)
   0x00000000004004c3 <+15>:    mov    -0x8(%rbp),%eax
   0x00000000004004c6 <+18>:    mov    %eax,-0x4(%rbp)
   0x00000000004004c9 <+21>:    pop    %rbp
   0x00000000004004ca <+22>:    retq   
End of assembler dump.

3番目のケース(a += 1

(gdb) disassemble foo
Dump of assembler code for function foo:
   0x00000000004004b4 <+0>:     Push   %rbp
   0x00000000004004b5 <+1>:     mov    %rsp,%rbp
   0x00000000004004b8 <+4>:     movl   $0x0,-0x8(%rbp)
   0x00000000004004bf <+11>:    addl   $0x1,-0x8(%rbp)
   0x00000000004004c3 <+15>:    mov    -0x8(%rbp),%eax
   0x00000000004004c6 <+18>:    mov    %eax,-0x4(%rbp)
   0x00000000004004c9 <+21>:    pop    %rbp
   0x00000000004004ca <+22>:    retq   
End of assembler dump.

4番目のケース(a = a + 1

(gdb) disassemble foo
Dump of assembler code for function foo:
   0x00000000004004b4 <+0>:     Push   %rbp
   0x00000000004004b5 <+1>:     mov    %rsp,%rbp
   0x00000000004004b8 <+4>:     movl   $0x0,-0x8(%rbp)
   0x00000000004004bf <+11>:    addl   $0x1,-0x8(%rbp)
   0x00000000004004c3 <+15>:    mov    -0x8(%rbp),%eax
   0x00000000004004c6 <+18>:    mov    %eax,-0x4(%rbp)
   0x00000000004004c9 <+21>:    pop    %rbp
   0x00000000004004ca <+22>:    retq   
End of assembler dump.

ご覧のとおり、コンパイラの最適化を有効にしなくても、addlsの後にmovがある最初のケースを除き、同じマシンコードを生成します。これは、ユーザーとして好きなものを使用し、コンパイラーに残りを任せることを意味します。

最後に、いとこ演算子*=/=にはpostfixprefixの対応するものがないことに注意してください。

21
none

++プレフィックスまたはポストフィックス演算子変更変数値。

int a = 0;
int b = a++; // b is equal to 0, a is equal to 1

またはプレフィックス:

int a = 0;
int b = ++a; // b = 1, a = 1

このように使用する場合、それらは同じです:

int a = 0;
++a; // 1
a++; // 2
a += 1; // 3
10
dreamzor

両方の演算子はnの値を1増やします。代入演算子とともに演算子を使用すると、両者の違いが存在します。

例えば:

最初のケース-ポストインクリメント演算子

int n=5;
int new_var;

new_var=n++;

print("%d",new_var);

出力= 5

2番目のケース

int n=5;
n+=1;
new_var=n;
print("%d",new_var);

出力= 6

これは、プリインクリメント演算子の結果と非常に似ています。

事前インクリメント演算子を使用した2番目のケース

int n=5;

new_var=++n;
print("%d",new_var);

出力= 6

6
Desert Ice

それらは一般的に同じであり、それらの違いを明確にする意味はありません。しかし、これら2つのステートメントの実装は実際には異なります。たとえば、a + = 1はassemberにコンパイルされます
a、1を追加
and a ++または++ aは
inc a
2つの異なるCPU動作であるため、効率に若干の違いが生じる可能性があります。

2
bigfish

これらの2つの演算子は似ているように見えるかもしれませんが、まったく異なっています。

プリミティブ型(ポインター、整数など)の場合、どちらも値を1ずつ増やします。ただし、C++クラスの場合、異なる演算子(operator+= vs. operator++)を呼び出します。実際、list<T>::iteratorなどの一部のクラスでは、i += 1は機能せず、i++を使用する必要があります。

さらに、それらは異なる値を生成します。 i += 1は(プリインクリメントのように)インクリメント後にiを生成しますが、i++はインクリメント前にiを生成します。したがって、

int a = 0, b = 0;
cout << (a+=1) << " " << b++ << endl;

1 0を出力します。 i += 1はプリインクリメントと同等であるため、場合によってはi += 1が生じる可能性があります

したがって、変数の増分については同じですが、すべての条件で完全な代替物ではないことに注意してください。

2
nneonneo

一部の人は違いに近づいていますが、非常に明確に述べる必要があります。

彼らは非常に異なる演算子です。

プリインクリメント演算子とポストインクリメント演算子は、変数の値がそれを囲む式で使用される前または後に変数の値を変更するために、INSIDE EXPRESSIONSで使用されるように設計されています。 postincrement演算子を使用する場合、変数のOLD値を使用して囲み式が評価され、その後で変数がインクリメントされます。

例えば:

i = 10;
j = i++;  // This causes j to be 10 while i becomes 11.

これが、ポストインクリメント演算子と呼ばれる理由です。変数はインクリメントされますPOST(AFTER)その値はより大きい式(ここでは代入式)で使用されます。

ただし、次の場合:

i = 10;
j = ++i; // Now both i and j will be 11 because the increment
         // of i occurs PRE (BEFORE) its value is used in the greater expression.
2
Tom Wetmore

少なくとも古いコンパイラー/コンピューター(基本的にCが生まれて10年か2年後)について+= 1かなり++より遅いことに誰も言及していないことに驚いています。 ++は、CPUが単一の命令を持っている可能性が最も高い増分です。 += 1は、値1をレジスターにロードし(その値をどこかに保存する可能性があります...どこかに)、追加を呼び出す必要があります。現在のコンパイラがこれを最適化するかどうかは言えませんが、そうだと思います。

1
chx

Stackoverflowは初めてですが、ここに2ペンスの価値があります。

質問が+ = 1ではなく+ =に関するものである場合。投稿された声明は

私は通常++または+ = 1を使用する状況に遭遇しますが、それらの違いはわかりません。

1は簡単に別の数字になったり、おそらく+ =?

結果に関しては、違いはありません(ポスターの値を使用)。両方とも1ずつ増加しますが、++は1だけ増加しますが、+ =はコーダーによって指定された値だけ増加します。edermanの例では1になります。例:

// Example 1:
num = 0;
num = ++;
// the result of num will be 1

// Example 2:
num = 0;
num = += 1;
// the result of num will be 1 the same as example 1

// Example 3:
num = 0;
num = += 2;
// the result of num will be 2.

// Example 4:
num = 0;
num = ++ 2;
// this would not compile as ++ will not except any value for the increment step it is assumed
// you will always want to increment by the value of 1

したがって、値を1だけ増やす場合は++を使用しますが、1だけ増やす必要がある場合は+ =を使用します

それが役に立つことを願っています。

1
Kevin Morrissey

++は値を1増やすために使用され、+ =を使用すると別の量だけ増やすことができます。

0
Alfa3eta