“++”和“+ = 1”运算符之间有什么区别?

时间:2012-10-20 11:51:13

标签: c++ loops integer auto-increment increment

在C ++循环中,我经常会遇到使用+++=1的情况,但我无法区分它们。例如,如果我有一个整数

int num = 0;

然后在循环中我做:

num ++;

num += 1;

他们都增加num的价值,但他们的区别是什么?我怀疑num++可以比num+=1更快地工作,但是如何?这种差异是否足以被忽视?

10 个答案:

答案 0 :(得分:79)

num += 1相当于++num

所有这些表达式(num += 1num++++num)将num的值增加1,但num++的值为{{ {1}} 之前增加了

插图:

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,因为它更短。

答案 1 :(得分:20)

前缀 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一起使用时,它们主要用作前缀操作。事实上,在我的机器上,它们生成相同的机器代码。您可以使用示例程序尝试此操作,例如:

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.

第二种情况(++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.

第三种情况(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.

第四种情况(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.

正如您所看到的,即使没有打开编译器优化,它们也会生成相同的机器代码,除了addl之后mov的第一种情况。这意味着您应该使用任何您喜欢的用户,让编译人员完成剩下的工作。

最后,请注意,表兄司机*=/=没有后缀前缀对应物。

答案 2 :(得分:9)

++前缀或后缀运算符更改变量值。

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

答案 3 :(得分:6)

两个运算符都将n的值增加1.当您将运算符与赋值运算符一起使用时,它们之间存在差异。

例如:

First Case --Post-Increment运算符

int n=5;
int new_var;

new_var=n++;

print("%d",new_var);

输出= 5

第二种情况

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

输出= 6

这与预增量运算符的结果非常相似。

使用预增量运算符的第二种情况

int n=5;

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

输出= 6

答案 4 :(得分:2)

它们通常是相同的,澄清它们之间的区别没有意义。但实际上这两个陈述实际上是不同的。 例如, a + = 1编译为assember是
    加一,1 和a ++或++ a是一个 效率可能会略有不同,因为它们是两种不同的CPU操作。

答案 5 :(得分:2)

有些人正在接近这种差异,但应该非常明确地说明:

他们是非常不同的运营商。

preincrement和postincrement运算符被设计为使用INSIDE EXPRESSIONS来在变量的值之前或之后更改变量的值,无论表达式是什么。使用postincrement运算符时,变量的OLD值用于计算封闭表达式,只有在此之后变量才会增加。

例如:

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

这就是它被称为postincrement运算符的原因。变量递增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.

答案 6 :(得分:2)

这两个操作符可能看起来很相似,但它们完全不同。

对于基本类型(指针,整数等),它们都将值递增1。但是,对于C ++类,它们调用不同的运算符(operator+=operator++);实际上,对于某些类,例如list<T>::iteratori += 1不起作用且必须使用i++

此外,他们产生不同的价值观。递增后i += 1生成i(如前递增),而i++在递增前生成i。因此,

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

打印1 0。由于i += 1相当于预增量,因此在某些情况下,可能会导致i += 1

因此,虽然它们对于递增变量是相同的,但应该意识到它们在所有条件下都不是完美的替代品。

答案 7 :(得分:1)

我很惊讶没有人提到至少对于旧的编译器/计算机(基本上是在C诞生并且在十年或两年之后)+= 1显着慢于{{1} }。 ++是CPU最有可能只有一条指令的增量。 ++需要将值1加载到寄存器中(可能在某处保存它的值)并要求添加。我不能说当前的编译器是否优化了它,但我怀疑它们是这样做的。

答案 8 :(得分: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,请使用+ =

希望这很有用。

答案 9 :(得分:0)

++用于将值增加1,而使用+ =则可以增加另一个量。