73

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?

E_learner
  • 3,512
  • 14
  • 57
  • 88
  • You should not worry about the implementation only the meaning of the expression. How the compiler implements the underlying code is irrelevant and the compiler will chooses the fastest safe to implement the meaning of the operation (in this case increment num by 1) which is likely to be exactly the same for POD. – Martin York Oct 20 '12 at 14:55
  • 1
    @DeadMG Defined behavior has been restored :D – Thomas Oct 20 '12 at 15:08
  • 31
    I'm 63 years old. What does "UB" mean? – Tom Wetmore Oct 20 '12 at 15:12
  • 2
    @TomWetmore [Undefined behavior](http://en.wikipedia.org/wiki/Undefined_behavior). – Thomas Oct 20 '12 at 15:20
  • 1
    about the efficiency , as I learned in lecture ++num is faster then num++ (if the purpose is only to increment num value) – URL87 Oct 20 '12 at 16:55
  • @URL87: Over generalization (by you, not your lecturer I am sure). When talking about POD there will be absolutely no difference. When we are talking about iterators, the standard pattern for implementing iterators will make the pre-increment version more effecient as a copy is not needed. In all other cases it will depend on the exact implementation. But as a general rule of thumb prefer pre-increment to post-increment because of the ubiquitous nature of iterators. – Martin York Oct 20 '12 at 17:14
  • @LokiAstari: so why there is no difference also in POD ? , look at the implementation in case of int - in prefix you should return (*this) however in postfix you should return new object , in this case - new int . Apparently it's true in all cases, not only in iterators . – URL87 Oct 20 '12 at 18:47
  • @URL87: Look at the generate assembly. – Martin York Oct 21 '12 at 01:00

10 Answers10

122

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.

Alexandre C.
  • 55,948
  • 11
  • 128
  • 197
  • Thank you all for your answer. – E_learner Oct 20 '12 at 12:07
  • 13
    Being shorter is certainly a point, but IMO not as important as the fact that `++a` is more consistently generalisable and guaranteed to work efficiently not just for `int` but also for any kind of iterator. – leftaroundabout Oct 20 '12 at 14:18
  • 6
    @leftaroundabout: Integers and iterators have nothing to do with one another. We aren't talking about pointers here (and the proper generalization of `i += 1` would be `std::advance (i, 1)`), and the OP seems not yet knowledgeable enough to complicate matters in such a way. I stand by my point: the only difference between `i += 1` and `++i` for integers (which is what is asked about) is a cosmetic one. – Alexandre C. Oct 20 '12 at 15:23
  • 2
    @AlexandreC. For iterators, there is no situation in which `std::advance(i, 1)` would work but `++i` would not. I don't think `advance` is the proper generalisation of `++i` for iterators. +1 on this answer though. – Seth Carnegie Oct 20 '12 at 17:27
  • 1
    @SethCarnegie: `std::advance (i, n)` is the proper generalization of `i += n`. – Alexandre C. Oct 20 '12 at 21:53
  • 1
    Regarding cosmetics, I find `i += 1` clearer and easier to spot in regular code. The brevity of `++i` sometimes hides it away a bit so I only really use it in loops. – Elliott Oct 20 '12 at 22:53
  • If you overload the ++n operator, would the definition of +=1 (automatically that is) – soandos Oct 21 '12 at 01:26
  • 2
    Side note: In my tests, ++i can generate more efficient assembly than i++ on some compilers (GCC from memory) because it can avoid the creation of an additional temporary. – sleep Oct 24 '12 at 15:01
46

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 movs. 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.

none
  • 11,793
  • 9
  • 51
  • 87
13

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
dreamzor
  • 5,795
  • 4
  • 41
  • 61
  • 2
    To be clear, `a += 1` also has a return value, but it's the value of `a` after the increment. – Dawson Oct 20 '12 at 11:54
  • 2
    Re *`a += 1` also has a return value*: So does `=`. That `=` returns a value is what makes statements such as `a = b = c = 0;` valid. – David Hammen Oct 20 '12 at 13:01
  • 3
    They don't have return values, they are _expressions_ and evaluate to something. – Seth Carnegie Oct 20 '12 at 17:29
  • 1
    @SethCarnegie: If you want to be pedantic, be entirely right. `=`, or as it's more generally known, `operator=` isn't an expression by itself. `a=b` is an expression involving `=` and two sub-expressions `a` and `b`. If the expression assigned to is a User Defined Type, `operator=` is a function and has a return type. – MSalters Oct 21 '12 at 13:13
  • @MSalters You are of course correct, but I was speaking to this specific case, which involves `int`s, so both I and you are entirely right. – Seth Carnegie Oct 21 '12 at 16:16
7

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

Desert Ice
  • 4,461
  • 5
  • 31
  • 58
  • 2
    There are two ++ operators, pre-increment (`++n`) and post-increment (`n++`). You only looked at post-increment. Try your comparison with pre-incrment. BTW, the recommended practice in C++ is to prefer pre-increment over post-increment when either of the two will do. – David Hammen Oct 20 '12 at 12:58
4

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 in different behaviour than i++.

So, while they are the same for incrementing variables, one should be aware that they are not perfect substitutes in all conditions.

nneonneo
  • 171,345
  • 36
  • 312
  • 383
2

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.

bigfish
  • 29
  • 3
  • 2
    The compiler also knows about this and removes any difference during optimization. – Bo Persson Oct 20 '12 at 14:49
  • I am sure the compiler has a lot of trouble on that optimization. To be clear I am being sarcastic. There will be no difference in the underlying instructions used. Any compiler written in the last 100 million years can do that optimization even the human brain. – Martin York Oct 20 '12 at 15:03
  • 1
    This is only true if the postincrement operator is used in isolation. If it is used inside a larger expression the generated assembly code will be different because the semantics are different. Please see the answer I provided for more information. Sorry I have to downvote this answer, but it is incorrect. – Tom Wetmore Oct 20 '12 at 15:07
2

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.
Martin York
  • 257,169
  • 86
  • 333
  • 562
Tom Wetmore
  • 233
  • 1
  • 6
  • Please learn how to use markdown. (there is a help button on the right that describes how to use it). – Martin York Oct 20 '12 at 14:59
  • Loki, Thanks for the tip. I usually post to "humanities" based groups who don't need code examples! Thank for adjusting the post for me. – Tom Wetmore Oct 20 '12 at 15:03
  • As you say, the preincrement and postincrement operators are different when used in larger expressions, or in a context where the result is used. But when used as a statement expression: `++i;` or `i++;`, where the result is discarded, they're effectively identical. There's no operator that increments an object without also yielding a result, so it's very common use use either `++i;` or `i++;` for that purpose. – Keith Thompson Oct 20 '12 at 22:37
1

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.

chx
  • 11,270
  • 7
  • 55
  • 129
  • I would be surprised at a decade time frame. Maybe a week after version 1 of the first compiler was released they added that peephole optimization. And 'significant' is probably not the adjective I would have chosen. – Martin York Oct 20 '12 at 15:05
  • I am not familiar with the history of C compilers. I know that theoretically what you say could be true 'cos the Backus-lead FORTRAN team in '54-'57 already wrote an optimizing compiler for that language so 15 years later sure someone could write an optimizing C compilter. – chx Oct 20 '12 at 15:10
  • @chx: You can't make that statement as a universal truth, even for old compilers. There's nothing in the C standard stating that the `+= 1` form requires that you load the value into a register and perform an addition. All the compiler is required to do is provide the appropriate semantics specified by the C language; this is one of the more obvious optimizations that could have been done very easily. You can't make any blanket statement about performance differences, only statements for a particular compiler revision. – Jason R Oct 20 '12 at 16:03
1

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.

Desert Ice
  • 4,461
  • 5
  • 31
  • 58
Kevin Morrissey
  • 179
  • 1
  • 7
-1

++ is used to increment value by 1, while using += you can increment by another amount.

Alfa3eta
  • 405
  • 2
  • 8