66

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

int num = 0;

然后在一个循环中我这样做:

num ++;

或者

num += 1;

它们都增加了 的值num,但它们的区别是什么?我怀疑num++可以比 工作得更快num+=1,但是如何?这种差异是否足够微妙以至于可以忽略不计?

4

10 回答 10

110

num += 1相当等价于++num

所有这些表达式 ( num += 1,num++++num) 都将 的值加num一,但 的值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

使用任何你喜欢的东西。我更喜欢++numnum += 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

+=operation 及其姐妹-=是更通用的解决方案,主要用于不同的数字。甚至可以说它们与 . 一起使用时是多余的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.

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

最后,请注意表亲运算符*=/=没有对应的后缀前缀

于 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

第二种情况

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

输出 =6

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

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

int n=5;

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

输出 =6

于 2012-10-20T11:56:45.993 回答
3

这两个运算符可能看起来很相似,但它们却大不相同。

对于原始类型(指针、整数等),它们都将值加一。但是,对于 C++ 类,它们调用不同的运算符(operator+=vs. 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可能会导致与i++.

因此,虽然它们对于递增变量是相同的,但应该知道它们在所有情况下都不是完美的替代品。

于 2012-10-20T23:25:41.133 回答
2

它们通常是相同的,没有意义来澄清它们之间的区别。但是这两个语句的执行方式其实是不同的。例如,a+=1 编译成汇编是
add a,1
而 a++ 或 ++a 是
inc a
效率上可能会有一些轻微的差异,因为它们是两种不同的 CPU 操作。

于 2012-10-20T14:06:15.277 回答
2

你们中的一些人正在接近差异,但应该非常清楚地说明:

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

preincrement 和 postincrement 运算符设计用于在表达式内部更改变量的值,无论是在变量的值用于包含它的任何表达式之前还是之后。当使用 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.
于 2012-10-20T14:51:23.910 回答
1

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

于 2012-10-20T15:03:39.567 回答
1

我是 Stackoverflow 的新手,但这是我的 2 便士。

如果问题是关于 += 而不是 +=1。张贴的声明是;

我通常会遇到使用 ++ 或 +=1 的情况,但我无法区分它们。

我认为 1 很容易成为另一个数字,或者写成 += 更好?

就结果而言,没有区别(使用海报值)。两者都将递增 1,但是,++ 只会递增 1,而 += 将递增 coder 指定的值,在 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 回答
0

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

于 2012-10-20T11:56:27.270 回答