Search

5.4 — Increment/decrement operators, and side effects

Incrementing and decrementing variables

Incrementing (adding 1 to) and decrementing (subtracting 1 from) a variable are so common that they have their own operators.

Operator Symbol Form Operation
Prefix increment (pre-increment) ++ ++x Increment x, then return x
Prefix decrement (pre-decrement) –– ––x Decrement x, then return x
Postfix increment (post-increment) ++ x++ Copy x, then increment x, then return the copy
Postfix decrement (post-decrement) –– x–– Copy x, then decrement x, then return the copy

Note that there are two versions of each operator -- a prefix version (where the operator comes before the operand) and a postfix version (where the operator comes after the operand).

The prefix increment/decrement operators are very straightforward. First, the operand is incremented or decremented, and then expression evaluates to the value of the operand. For example:

This prints:

6 6

The postfix increment/decrement operators are trickier. First, a copy of the operand is made. Then the operand (not the copy) is incremented or decremented. Finally, the copy (not the original) is evaluated. For example:

This prints:

6 5

Let’s examine how this line 6 works in more detail. First, a temporary copy of x is made that starts with the same value as x (5). Then the actual x is incremented from 5 to 6. Then the copy of x (which still has value 5) is returned and assigned to y. Then the temporary copy is discarded.

Consequently, y ends up with the value of 5 (the pre-incremented value), and x ends up with the value 6 (the post-incremented value).

Note that the postfix version takes a lot more steps, and thus may not be as performant as the prefix version.

Here is another example showing the difference between the prefix and postfix versions:

This produces the output:

5 5
6 4
6 4
6 4
7 3

On the 8th line, we do a prefix increment and decrement. On this line, x and y are incremented/decremented before their values are sent to std::cout, so we see their updated values reflected by std::cout.

On the 10th line, we do a postfix increment and decrement. On this line, the copy of x and y (with the pre-incremented and pre-decremented values) are what is sent to std::cout, so we don’t see the increment and decrement reflected here. Those changes don’t show up until the next line, when x and y are evaluated again.

Best practice

Strongly favor the prefix version of the increment and decrement operators, as they are generally more performant, and you’re less likely to run into strange issues with them.

Side effects

A function or expression is said to have a side effect if does anything that persists beyond the life of the function or expression itself.

Common examples of side effects include changing the value of objects, doing input or output, or updating a graphical user interface (e.g. enabling or disabling a button).

Most of the time, side effects are useful:

The assignment operator in the above example has the side effect of changing the value of x permanently. Even after the statement has finished executing, x will still have the value 5. Similarly with operator++, the value of x is altered even after the statement has finished evaluating. The outputting of x also has the side effect of modifying the state of the console, as you can now see the value of x printed to the console.

However, side effects can also lead to unexpected results:

C++ does not define the order in which function arguments are evaluated. If the left argument is evaluated first, this becomes a call to add(5, 6), which equals 11. If the right argument is evaluated first, this becomes a call to add(6, 6), which equals 12! Note that this is only a problem because one of the arguments to function add() has a side effect.

There are other cases where C++ does not specify the order in which certain things are evaluated (such as operator operands), so different compilers may exhibit different behaviors. Even when C++ does make it clear how things should be evaluated, historically this has been an area where there have been many compiler bugs. These problems can generally all be avoided by ensuring that any variable that has a side-effect applied is used no more than once in a given statement.

Warning

C++ does not define the order of evaluation for function arguments or operator operands.

Best practice

Don’t use a variable that has a side effect applied to it more than once in a given statement. If you do, the result may be undefined.


5.5 -- Comma and conditional operators
Index
5.3 -- Modulus and Exponentiation

55 comments to 5.4 — Increment/decrement operators, and side effects

  • Len

    "Rule: Favor pre-increment and pre-decrement over post-increment and post-decrement. The prefix versions are not only more performant, you’re less likely to run into strange issues with them."

    No wonder I keep running into strange issues. From now on I will refer to this language as ++C.

  • Hey Alex! something is wrong. I am unable to write xminusminus (post decrement of a variable 'x'). When I type xminusminus and looking back to my posted comment, I only see a single minus after x (something like 'x-'). That is not a big problem and you can ignore this . I am only trying to clear that you made a mistake in the table above. Sorry for this extra comment.

    It is okay when I use [code] tag.

    Take a look at the last row of the table (the table which is showing the two versions of increment-decrement operators) :

    "Postfix decrement (pre-decrement)" |   --   |  x--  | Evaluate x, then decrement x

    should be:

    "Postfix decrement (post-decrement)" |  --  |  x--  |  Evaluate x, then decrement x

    One question. I m not very good in math. Can I still be a good programmer? How math is related to programming?

    • Alex

      What browser are you using? It looks okay to me on Chrome, Firefox, and IE.

      As for programming and math, it depends on what kind of programming you want to do. If you're going to do complicated stuff with algorithms, 3d graphics, probability, or simulations, then yes, having a good math background is important. If you're going to do business programming, or functionality for web pages, or user interfaces, then you probably won't need much math.

      What's more important is being good at logic.

      • I m using chrome. Thnx.
        Looks like you didn't noticed what I said.   Alex I was talking about the table (post decrement, pre decrement table). You made a typo I think, in the last row of table.

        Postfix-decrement (pre-decrement)

        Should be:

        Postfix-decrement (post-decrement)

        Hope it is clear now.

  • am

    Can anyone explain why the output is 11 9 11?

    • Alex

      Honestly, I'm not sure.

      operator<< evaluates from left to right, so I'd expect the following to happen: a = 10 ++a = 11, which gets printed. a++ means 11 gets printed, a is incremented to 12. --a = 11, which gets printed. So I'd expect 11 11 11. But Visual Studio 2010 and 2013 prints 11 9 11. Visual Studio 2008 prints 10 9 11. So even different compilers don't agree. It's possible that the compilers just aren't handling this case correctly. Which would be more evidence not to use a variable that has a side effect applied to it more than once in a given expression.

  • techsavvy....aye

    Thanks,Alex.

  • techsavvy....aye

    Hi! Alex.
    The program u have given above is displaying a blank o/p what could be the possible problem?
    please help!

    • Alex

      This program doesn't print anything, so there's no output.

      I updated the sample program to print value, so you can see whether it equals 11 or 12 on your compiler.

Leave a Reply

You can use these HTML tags

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">