• Forum
  • Lounge
  • why ++i is better than i++ (when applica

 
why ++i is better than i++ (when applicable)

Pages: 123
I have lots of time to think when I drive back and forth to and from school. Today I examined my preference for i++ over ++i when they accomplish the same thing.

I've noticed that for some strange reason, I tend to both type, and think rhythmically. When I program, I sometimes silently say to myself what I am write. One of the main factors,, I presume, in my preference, is that ++i is easier to say. It rolls off the tongue smoother.

Secondly, I think that ++i is easier to type than i++. Well, at least ++somevar. When you are to make the decision to type a variable increment, you know before you start that you will be typing ++. Before you have even fully realized the name of the specific variable, you can have already instinctually typed your ++. I personally have a strange style of typing where I tend to rest my pinky on the shift key in between thoughts / sentences / statements. Probably this comes from the fact that sentences start with capital letters. This means that my pinky usually in a more suited position to begin to type ++ than it will be immediately after typing some identify.

There it is. That is why only fools use i++ in preference of ++i;) And those are the types of pointless thoughts the run through my brain while it sits idle.
Except they do different things and there are situations to use one as opposed to the other.
In many instances pre increment is faster/ more efficient, i.e. iterators.
Except they do different things and there are situations to use one as opposed to the other.

Right, but when they accomplish the same thing...
In many instances pre increment is faster/ more efficient, i.e. iterators.

But optimization's should take care of that.
But optimization's should take care of that.
Maybe for container implementations where iterators are pointers, but that can't be guaranteed and most (AFAIK) are implemented as class objects.
My preference for ++i is simple:

There are some situations where ++i might be a better performer.

There are no situations where i++ will ever be a better performer (unless the operators are overloaded incorrectly or the code is bugged)


Therefore since there's a possible benefit to the prefix form, and no possible benefit to the postfix form, I always prefer the prefix form unless I have specific need of the postfix form.
Last edited on
++Disch;
++Disch;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class SomeNum
{
    int i;
public:
    SomeNum operator++() // prefix
    {
        i = i + 1;
        return *this;
    }

    SomeNum operator++(int) // postfix
    {
        SomeNum copy(*this);
        i = i + 1;
        return copy;
    }
};


The post-fix operator often makes a copy of the current object. It's simply an extra step which may be expensive if you have a big class.
Last edited on

There are no situations where i++ will ever be a better performer (unless the operators are overloaded incorrectly or the code is bugged)


Oh, really?

If you don't need the result, a sufficiently intelligent compiler should optimize both to the same machine code.

But if you need the result, i++ is sometimes faster than ++i for primitive types, and I don't know of any compiler that would be able to change the code from ++i to i++ *if you need the result*.

a = b++; // can be processed in 1 CPU cycle, inc and mov executed on different pipelines
a = ++b; // forces RAW and possible pipeline stall

I know they are both doing slightly different thing, but if you can decide, you should always use post-increment where possible (applies to primitive types only).
Last edited on
Talking about built-in types, following rapidcoder's example:

Say 'a' is 'eax' and 'b' is 'ebx'.

a = b++; resolves to:
mov eax, ebx
inc ebx


Where
a = ++b; resolves to:
inc ebx
mov eax, ebx


So the operations are the same, but with a different order.
Remember: this ONLY for built-ins.

If you don't need the old return value, you should use ++b anyways. I don't have a single reason why you wouldn't use it in such a situation, except with classes.

Also:
rapidcoder wrote:
forces RAW and possible pipeline stall

What did you mean?

EDIT: Ah, I understand what you mean now, but you may want to explain this for newbie users.
Last edited on
Whether to use ++i or i++ depends on the context.

For example for fundamental types there is no any difference between

for ( T i = 0; i < 10; i++ ) { /* ... */ }
and
for ( T i = 0; i < 10; ++i ) { /* ... */ }

where T is some integer type.
a = b++; // can be processed in 1 CPU cycle, inc and mov executed on different pipelines
a = ++b; // forces RAW and possible pipeline stall

I know they are both doing slightly different thing, but if you can decide, you should always use post-increment where possible (applies to primitive types only).


They aren't doing slightly different things. They are doing different things.

Obviously where context matters, you use the one that is appropriate. Where context doesn't matter, it's perfectly efficient to use either in the case of native types and more efficient in many cases to use the prefix version with user-defined types. So, it's reasonable to prefer ++i when context doesn't matter, because the compiler will generate the same code for native types and the most efficient code for user-defined types.

@ rapidcoder: That's a valid point. My understanding of low level pipelinine behavior is admittedly less than I'd like.... but AFAIK it's impossible to accomplish a = ++b without the possible pipeline stall no matter what you do. For example:

1
2
b++;
a = b;


This code will have the same effect (by using the postfix version), and the same read/write, and therefore the same potential pipeline stall.

So it's not that prefix is any slower than postfix. It's just that modifying a variable right before reading it is slower.

So I'm standing by my original statement.

Though I welcome further discussion on the topic. Especially if my understanding is incorrect.
Last edited on
Just like with many other things that are 'good habit', I use pre-increment and pre-decrement because it is a 'good habit', as explained in Disch's original post. There are times when I use post-increment or post-decrement, like mymap.erase(it++); because I use the return value of the previous state.

I do have to wonder, in C++11, is there some way to optimize overloaded post-increment/decrement operators? it seems like the making a copy and changing the state is a prime candidate for move constructing but I don't see how it could be easily done without some memory magic.
Last edited on
@LB:

mymap.erase(it++);

You should never ever do that. It's very bad. Iterators become invalid once you erase them, and incrementing an invalid iterator is undefined.

This is why erase returns an iterator:

 
it = mymap.erase(it);
Huh? I'm erasing the old iterator from before it got incremented...is the fact that it works for me implementation defined? Or does it have to do with all existing iterators becoming invalid?
Last edited on
Disch wrote:
mymap.erase(it++);

You should never ever do that. It's very bad. Iterators become invalid once you erase them, and incrementing an invalid iterator is undefined.


That is actually perfectly valid for containers that don't invalidate iterators to other elements in the container when erase is used. it is advanced before the map element is erased. erase works on a (temporary) copy.

It's good not to be in the habit of doing that though, because it's obviously not safe on all containers.
Ah, yeah. I thought std::map didn't invalidate other iterators besides the one being erased. I'll get out of that habit now.
Last edited on
Pages: 123