66

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

int num = 0;

そしてループで私は:

num ++;

また

num += 1;

どちらも の値を増やしますがnum、違いは何ですか? num++よりも速く動作するとは思えませnum+=1んが、どうすればよいでしょうか? この違いは無視できるほど微妙ですか?

4

10 に答える 10

110

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

これらの式 ( num += 1num++および++num) はすべて、 の値をnum1 ずつ増やしますが、 の値はnum++、増やすの値です。num

図:

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

于 2012-10-20T11:53:24.973 に答える
39

接頭辞接尾辞の操作は、試験問題の最適な候補です。

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、ほとんどがプレフィックス操作として機能します。実際、私のマシンでは、同じマシン コードが生成されます。次のようなサンプル プログラムを使用して、これを試すことができます。

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.

ご覧のとおり、s のaddl後にある最初のケースを除いて、コンパイラの最適化がオンになっていない場合でも、同じマシン コードを生成しmovます。これは、ユーザーとして好きな方を使用し、残りはコンパイラーに任せるべきであることを意味します。

*=そして最後に、従兄弟演算子とには対応する接尾辞と接頭辞/=がないことに注意してください。

于 2012-10-20T17:25:26.220 に答える
13

++置演算子または後置演算子は変数値を変更します。

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
于 2012-10-20T11:52:54.857 に答える
7

どちらの演算子も、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

于 2012-10-20T11:56:45.993 に答える
3

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

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

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

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

印刷し1 0ます。i += 1はプリインクリメントと同等であるため、i += 1場合によっては、とは異なる動作が発生する可能性がありi++ます。

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

于 2012-10-20T23:25:41.133 に答える
2

それらは一般的に同じであり、それらの違いを明確にする意味はありません。しかし、これら 2 つのステートメントの実装は実際には異なります。たとえば、a+=1 をアセンバーにコンパイルすると
、add a,1
と a++ または ++a が
inc a
になります。これらは 2 つの異なる CPU 操作であるため、効率に多少の違いがある場合があります。

于 2012-10-20T14:06:15.277 に答える
1

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ずつインクリメントする必要がある場合は、+=を使用します。

それがお役に立てば幸いです。

于 2012-10-20T22:48:53.537 に答える
1

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

于 2012-10-20T15:03:39.567 に答える
0

++ は値を 1 インクリメントするために使用されますが、+= を使用すると別の量だけインクリメントできます。

于 2012-10-20T11:56:27.270 に答える