i++ , or ++i, which is faster?

O

Old Wolf

Clark said:
(e-mail address removed) (Alf P. Steinbach) said:

Both (++i) and (i++) have the exact same side effect, which is to
increment i. i can't see how one is any more likely to cause UB than
the other.

You are correct, of course, if i has a built-in type.

However, in my experience, people write side-effect code
more often with i++ than they do with ++i.

There is also a common misconception that ++i must perform
its side-effect before it is evaluated, thus being less
likely to cause UB.
 
A

Alf P. Steinbach

* Clark S. Cox III:
I didn't say they meant the same thing (they don't, they have different
values), but they do have the same side effect.

That seems like a definition of what you mean by "side effect", presumably
the standard's technical and context-free one of "changes in the state of
the execution environment".

Outside of technical standardeese (?) what we mean by "side effect" is not
just any change to the execution environment. With ++i used as a statement
the technical _side_ effect as defined by the standard, is the primary and
only effect. Which isn't very meaningful in natural language discussions,
such as the one we were having, but is one of many technical definitions.

In short, when retrofitting that special meaning of "side-effect" to the
earlier discussion it becomes meaningless, so I hadn't considered that.

If you expect either operator to increment i, then you are relying on
side effects.

True, but irrelevant.

++i does exactly that, while i++ does a little more, where the little more
is _only_ meaningful/useful for use in non-statement expressions that alter
the execution environment.

Instead of writing more about that here I refer you to an opinion piece I
wrote that's been extensively reviewed, see
<url: http://home.no.net/dubjai/win32cpptut/html/w32cpptut_01_02_11.html>.
 
O

Old Wolf

Alf said:
* Clark S. Cox III:

That seems like a definition of what you mean by "side effect", presumably
the standard's technical and context-free one of "changes in the state of
the execution environment".

Outside of technical standardeese (?) what we mean by "side effect" is not
just any change to the execution environment. With ++i used as a statement
the technical _side_ effect as defined by the standard, is the primary and
only effect.

The side effect is that 'i' is incremented.
The expression evaluates to (i + 1).

"side effect" is a clearly-defined term in the Standard.
Talking about a "primary and only effect" only seems to
muddy the waters, to me.
++i does exactly that, while i++ does a little more, where the little
more is _only_ meaningful/useful for use in non-statement expressions
that alter the execution environment.

What is this 'little more' of which you speak?
The page you link to doesn't say.

++i and i++ have /exactly the same/ side-effect.

Can you give a code example of where i++ does something that
++i doesn't?

i++ means exactly the same thing as (++i - 1), if we don't
run into integer overflow.

There is no possible piece of code where the behaviour is
undefined, but changing 'i++' to '++i' renders the behaviour
well-defined. [where 'i' is an int]
 
H

Howard

Old Wolf said:
Can you give a code example of where i++ does something that
++i doesn't?

The operators return different values given the same input. I'd say that
qualifies as doing something different.

int i = 0;
std::cout << i++ << std::endl; // print 0
i = 0;
std::cout << ++i << std::endl; // prints 1

The first example (i++) prints the value before incrementing (0). Since the
action of incrementing is of no consequence to the result, it's often
considered a side effect.

The second example (++i) prints the value after incrementing (1). Since the
action of incrementing is integral to obtaining the correct result to print,
it's not considered a side effect, but rather the primary effect.

-Howard
 
?

=?ISO-8859-1?Q?Tr0n=B2?=

Old said:
Alf P. Steinbach wrote:
What is this 'little more' of which you speak?
The page you link to doesn't say.

If you don't know that - I don't think you have the right to try and
argue your _opinion_ on a public forum.

I think you can optimize the code a fraction to minimize the cost, but
I'm sure there are still places that have i++ do more work than ++i
simply because it returns a different value.

While I'm at it, I might as well include my opinion on the side effect.

I see it as the returning value.
++i has the side effect of "i + 1" (if you have "j = ++i" you get j = i)
and increases i.
i++ has the side effect of "i" ("j = i++" makes j = i - 1) and increases i.

You can either view it this way, or in reverse (returning the value
isn't the side effect, but changing i is). Either way they are different.
 
A

Alf P. Steinbach

* Old Wolf:
The side effect is that 'i' is incremented.
The expression evaluates to (i + 1).

"side effect" is a clearly-defined term in the Standard.
Talking about a "primary and only effect" only seems to
muddy the waters, to me.

Then you shouldn't have used the term in its more common meaning
earlier in the thread... ;-)

What is this 'little more' of which you speak?
The page you link to doesn't say.

Does, too. (I'm on the level.)

++i and i++ have /exactly the same/ side-effect.

For a specific definition of "side-effect" that renders your own earlier
comment in this thread,

"However, in my experience, people write side-effect code
more often with i++ than they do with ++i"

meaningless.

Did you mean, "people use i++ more often ++i"?

Well, I don't believe it.

Can you give a code example of where i++ does something that
++i doesn't?

The standard specifies a copy operation for i++, and no such for ++i.

i++ means exactly the same thing as (++i - 1), if we don't
run into integer overflow.

Nope.

First, formally, you're talking about built-in types, I presume. Even
there (and disregarding overflow) your expression is not quite equivalent.
It cannot be used for 'bool', preserving the type of the expression.

Second, in practice, as noted above, the standard specifies a copy operation
for i++, but none such for ++i, which means that in the program below, although
both expressions are formally Undefined Behavior instead of the more
reasonable Unspecified, in practice the ++i-1 expression can at most produce
x = 2, while the j++ expression can at most produce y = 1:

#include <iostream>
#include <ostream>

int main()
{
int i = 0;
int j = 0;

int const x = (++i - 1) + (++i - 1); // Formally UB.
int const y = (j++) + (j++); // Formally UB.
std::cout << x << ", " << y << std::endl;
}

Hence, in code that has UB in this way, but works with a given version
of a given compiler with given options (not uncommon), it's absolutely
not a good idea to replace (i++) with (++i-1).

Summing up: the purported equivalence does not hold formally, and it
does not hold in practice.

There is no possible piece of code where the behaviour is
undefined, but changing 'i++' to '++i' renders the behaviour
well-defined. [where 'i' is an int]

Probably you meant to write,

"changing 'i++' to '(++i - 1), disregarding overflow,".

If so then I think that's right: for 'int', and disregarding overflow.

However, people tend to write side-effect based code more often with
i++, because that's what it's made for -- it's a convenience notation
for side-effect based code, as of 2005 generally premature optimization.
 
S

Swampmonster

I see it as the returning value.
++i has the side effect of "i + 1" (if you have "j = ++i" you get j = i)
and increases i.
i++ has the side effect of "i" ("j = i++" makes j = i - 1) and increases i.

You can either view it this way, or in reverse (returning the value
isn't the side effect, but changing i is). Either way they are different.

No, they are not different. At least not if you define "side effect" as
"every change to an objects internal state". Or more precisely, every
change to any state at all - but also _only_ changes to some state.
i.e. things that you can't do in a functional programming language.
BTW the term "side effect free" appears a lot in the description of
functional languages (like e.g. SML), and functional languages do not
forbid you to return values - returning values is all you can do in
functional languages.

So with my definition of "side effect" a function like "atoi" has none,
a function like "exit" is _only_ useful for it's side effects, and a
function like "getch()" has both, a useful side effect and a useful
return value.

Consider this:

int foo_pp(int& n) {
return n;
}

int pp_foo(int& n) {
return n + 1;
}

int bar_pp(int& n) {
n = n + 1;
return n - 1;
}

int pp_bar(int& n) {
n = n + 1;
return n;
}

The return value of "foo_pp(i)" and "bar_pp(i)" is equal, namely the
value of i before the function was called.
The return value of "pp_foo(i)" and "pp_bar(i)" is equal as well,
namely "the value of i before the function was called plus 1".
The side-effects (i.e. changes to i's internal state) of "foo_pp(i)"
and "pp_foo(i)" are equal, namely none.
The side-effects of "bar_pp(i)" and "pp_bar(i)" are equal, namely
the value of i will have been incremented by 1 after the function has
returned.

Also "i++" and "++i" have exactly the same side-effect. As long as
integral types are concerned. And talking about UDTs and side-effects
and stuff in general is not really meaningful since I could choose to
do nothing in the implementation of either operator ++ or have the
computer order a pizza if I feel like doing so. Same for the return
value. I could wrap a double inside a UDT, but decide to have my
operator ++ (post) return 42 as an int and my operator ++ (pre)
return the string representation of the system time in a std::string.
The return value _and_ the side effects are completely up to the "U"
who defines that UDT.

BTW: If we say "i" is of some integral type, then "i + 1" is not an
effect - it's a value. Or an expression that has a value but no
effect. In any way, no (state) change - which would be something I
expect when I read "effect".
Of course with UDTs it could be all different, but see above.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Staff online

Members online

Forum statistics

Threads
474,298
Messages
2,571,542
Members
48,284
Latest member
RedaBruno6

Latest Threads

Top