问题
In a loop in C++, I usually encounter situations to use ++
or +=1
, but I can't tell their difference. For instance, if I have an integer
int num = 0;
and then in a loop I do:
num ++;
or
num += 1;
they both increase the value of num
, but what is their difference? I doubt num++
could work faster than num+=1
, but how? Is this difference subtle enough to be ignored?
回答1:
num += 1
is rather equivalent to ++num
.
All those expressions (num += 1
, num++
and ++num
) increment the value of num
by one, but the value of num++
is the value num
had before it got incremented.
Illustration:
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
Use whatever pleases you. I prefer ++num
to num += 1
because it is shorter.
回答2:
prefix and postfix operations are perfect candidates for exam questions.
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 and its sister -=
are more general solutions mostly intended to be used with different numbers. One might even say they are redundant when used with 1
. When used with 1
they mostly act as a prefix operation. In fact on my machine they produce the same machine code. You can try this by using an example program such as:
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;
}
and disassembling in gdb
which would give:
first case (a++
) (different)
(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.
second case (++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.
third case (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.
fourth case (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.
As you can see they produce the same machine code even without compiler optimizations turned on except the first case which has addl
after mov
s. This means that you should be using whichever you like as a user and let the compiler guys do the rest.
And lastly, note that cousin operators *=
and /=
have no postfix and prefix counterparts.
回答3:
The ++
prefix or postfix operators change the variable value.
int a = 0;
int b = a++; // b is equal to 0, a is equal to 1
Or prefix:
int a = 0;
int b = ++a; // b = 1, a = 1
If used like this, they are the same:
int a = 0;
++a; // 1
a++; // 2
a += 1; // 3
回答4:
Both the operators increase the value of n by 1. The difference between them exists when you use the operators along with the assignment operator.
For example:
First Case --Post-Increment operator
int n=5;
int new_var;
new_var=n++;
print("%d",new_var);
Output=5
Second Case
int n=5;
n+=1;
new_var=n;
print("%d",new_var);
Output =6
This is very similar to what pre-increment operator would result in.
Second Case using Pre-increment operator
int n=5;
new_var=++n;
print("%d",new_var);
Output =6
回答5:
They are generally the same and there is no significance to clarify the difference between them. But the implementing of these two statement are in fact different.
For example,
a+=1 compiling to assember is
add a,1
and a++ or ++a is
inc a
There may be some mildly difference in efficiency because they are two different CPU operation.
回答6:
Some of you are approaching the difference, but it should be stated very clearly:
THEY ARE VERY DIFFERENT OPERATORS.
The preincrement and postincrement operators are designed to be used INSIDE EXPRESSIONS to change the value of the variable either BEFORE or AFTER the value of the variable is used in whatever expression encloses it. When using the postincrement operator the OLD value of the variable is used to evaluate the enclosing expression and only after that is the variable incremented.
For example:
i = 10;
j = i++; // This causes j to be 10 while i becomes 11.
This is why it is called the postincrement operator. The variable is incremented POST (AFTER) it's value is used in the greater expression (here an assignment expression).
However, if you do:
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.
回答7:
These two operators may appear to be similar, but they are quite different.
For primitive types (pointers, integers, etc.) they both increment the value by one. But, for C++ classes, they call different operators (operator+=
vs. operator++
); indeed, for some classes, like list<T>::iterator
, i += 1
does not work and i++
must be used.
Furthermore, they produce different values. i += 1
produces i
after incrementing (like a preincrement), while i++
produces i
before incrementing. Thus,
int a = 0, b = 0;
cout << (a+=1) << " " << b++ << endl;
prints 1 0
. Because i += 1
is equivalent to a preincrement, in some cases, i += 1
may result
So, while they are the same for incrementing variables, one should be aware that they are not perfect substitutes in all conditions.
回答8:
I am surprised noone mentions that at least for old compilers / computers (basically when C was born and a decade or two after) += 1
will be significantly slower than ++
. ++
is an increment which the CPU most likely has a single instruction for. += 1
requires loading the value 1 into a register (likely saving the value of it... somewhere) and calling for an addition. I can't say whether current compilers optimize this out but I suspect they do.
回答9:
I'm new to Stackoverflow but here's my 2 pence worth.
If the question is about += and not +=1. The statement posted was;
I usually encounter situations to use ++ or +=1, but I can't tell their difference.
I think the 1 could just have easily been another number or perhaps better written as +=?
In terms of the result there is no difference (using the posters values). Both will increment by one, however, ++ will only increment by 1 whereas += will increment by the value specified by the coder, in ederman's example this happens to be 1. For Example:
// 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
So if you only want to increment a value by 1 I would use ++ but if you need to increment by more the 1 use +=
Hope that is useful.
回答10:
++ is used to increment value by 1, while using += you can increment by another amount.
来源:https://stackoverflow.com/questions/12988140/what-is-the-difference-between-and-1-operators