Why to avoid postfix operator in C++? [duplicate] - c++

This question already has answers here:
Prefix/Postfix increment operators
(3 answers)
Closed 9 years ago.
I heard a professor saying "Avoid postfix operator where the context allows to choose prefix". I search but I didn't found related posts in stackoverflow that explaining this.
Why to prefer prefix operator++ to postfix operator++ when we have the ability to choose either one?

The prefix operator++ does a single operation -- increment the value.
The postfix operator++ does three operations -- save the current value, increment the value, return the old value.
The prefix version is conceptually simpler, and is always (up to bizarre operator overloads) at least as efficient as the postfix version.

I'm pretty sure your professor is talking about the old speed difference between the prefix and postfix ++ operator. I'm also pretty sure it no longer matters which you choose as modern compilers usually are smart enough to recognize if it can be optimized out.
Also, depending on your code you might be required to use one or the other for correctness.

The prefix operator is potentially faster than the postfix operator, depending on the type on which it's operating. It should never be slower.
For most intrinsic types, the speed should be identical. However, many custom iterators need to make an extra copy of some state object in order to properly implement the postfix operator.

In order to implement the postfix operator, a copy of the original object has to be taken because that's what gets returned back to you.
For the prefix operator, you get the new object back, saving the copy overhead.
Some folk (rightly) will tell you that the compiler will optimise out unintentional postfix copies; for example in code like for (int n = 0; n < large; n++)
I'd always prefer to see ++n.
Infact, I'd rather the language be called ++C; not C++!

There's no real reason, except for stylistic issues. One noted
specialist recommended it once, and everyone blindly followed,
although the measures I did indicated that it made no
difference.
If you're starting on a green fields project, I'll use prefix,
but the motivation is just to avoid stupid discussions about the
issue. If I'm working on existing code, I'll continue to use
whatever was most common, because in real code, it makes
absolutely no difference, despite claims to the contrary.

Related

Double increment on an integer variable, does it work as intended? [duplicate]

This question already has answers here:
Multiple preincrement operations on a variable in C++(C ?)
(2 answers)
Closed 6 years ago.
I have some code with lines which increment a counter.
++ count;
Sometimes I have an if condition which means I should increment count by 2.
count += 2;
Does "double increment'ing" work in the same way?
++ ++ count;
It would be helpful to know if both C and C++ compilers interpret this the same way.
As this is clearly syntactically correct, the question that remains is: "Is this UB because of unsequenced writes?"
It is not (in C++11 and later) because
5) The side effect of the built-in pre-increment and pre-decrement operators is sequenced before its value computation (implicit rule due to definition as compound assignment)
(From here)
So the code is fine as of C++11.
However, the sequencing rules were different before that, and pre-C++11, the code actually has UB.
In C, that code does not even compile.
The fact that the behavior is different between C and C++ and even between different C++ standards and that this question arises in the first place is a hint that the simple count += 2; is the safer and more readable version. You should prefer it over the "cute and clever" ++ ++count;.
There are two methods. One that obviously works, one where you have to ask a question on StackOverflow. There are comments saying "in C++ 11 or later"... How sure are you that your C++ code runs with C++ 11 and not something older? Even if you use extensions that were not part of an earlier language, your language could be C++0x with some extensions.
Clearly you shouldn't care whether the second method works or not, but use the one that obviously works.

Ampersand and square brackets priority

I see a lot of programmers using brackets around an expression, e.g. :
&(tab[i]) /* I use `&tab[i]`. */
I think it isn't necessary, because the [] operator has a greater priority than & operator. So, why do they use brackets ?
For sake of clarity. Not everyone has all the operator precedences memorized.
I'd say there are basically two reasons:
The programmer isn't sure about operator precedence and codes defensively
To make absolutely clear for every reader (who may not have the precendence memorized) what is going on
It is indeed not necessary because postfix operators always have higher precedence than unary operators.
The people that use parens in &(tab[i]) use them for the same reason they use it in the expression (8 * 5) / 2.
In a recent question, someone had to decypher code like --p---> x < 0. Just like your code, that code is unambiguous as per C++ parsing rules.
However, humans don't always remember all of these complex rules, so many programmers make it a habit to use parens in situations that might look not totally clear to others (or to themselves). It is documenting the real intention of the code.
This is a Good Thing To Do™
Because they find it clearer? Especially for something like this:
int *a[];
Is that a pointer to an array of ints or an array of pointers to int?

Optimized code: is ++p faster than p++? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Is there a performance difference between i++ and ++i in C++?
In C++, I see people frequently use ++p in a for loop or elsewhere, where you want to increment a value, but not use the return value. I've heard this is more efficient because p++ returns the value before incrementing, and thus requires a temporary space.
But, it feels that even a very ignorant compiler will pull out that return value as dead code (as long as the increment code is inlined, and so the compiler can see that the return value wasn't necessary).
I'm trying to come up with a good example where, using some sort of iterator, iter++ will actually create the copy (even though the return value of iter++ is not used.
After all, we don't really frequently consider register allocation either when we write code with iterators.
I learned to use p++ simply because that's what the book I learned from did. Is preferring ++p when no return value is used an archaic practice, or simply part of elegant coding? And why is the language not called ++C then?
p++ is slower only when ++p doesn't do the job - i.e. when you actually use the return value. Otherwise, the compiler will optimize the code to the same thing.
People prefer using ++i instead of i++ because it describes better what you intend to do: increment i, more than increment i and return the old value. Of course, you tend to stick to old habits. If you're used to writing i++, that's ok, unless the coding standards of the company you work for mandate you use ++i.
Chapter 3 of D&E: ``I picked C++ because it was short, had nice
interpretations, and wasn't of the form "adjective C."' In C, ++ can,
depending on context, be read as "next," "successor," or "increment,"
though it is always pronounced "plus plus." The name C++ and its
runner up ++C are fertile sources for jokes and puns -- almost all of
which were known and appreciated before the name was chosen. The name
C++ was suggested by Rick Mascitti. It was first used in December of
1983 when it was edited into the final copies of [Stroustrup,1984] and
[Stroustrup,1984c].
Chapter 1 of TC++PL: ``The name C++ (pronounced
"see plus plus") was coined by Rick Mascitti in the summer of 1983.
The name signifies the evolutionary nature of the changes from C; "++"
is the C increment operator. The slightly shorter name "C+" is a
syntax error; it has also been used as the name of an unrelated
language. Connoisseurs of C semantics find C++ inferior to ++C. The
language is not called D, because it is an extension of C, and it does
not attempt to remedy problems by removing features. For yet another
interpretation of the name C++, see the appendix of [Orwell,1949].''
Sauce.
Depending on the iterator, creating a copy can be an extremely time consuming task (think about a naive, stack based iterator for a binary search tree). I suppose you realize that though, and that's not your real question :). Anyway, as far as I'm aware, the compiler is not required to optimize i++ to ++i.
As it's not required to optimize it, I would think it's better to err on the side of caution and stick with ++i.

Why does postfix operator++ have higher precedence than prefix operator++?

Defined this way, we can do neither ++x++ nor ++x--. But on the other hand, both (++x)++ and (++x)-- are useful expressions: (++x)++ increments x by two and returns the value "in the middle", while (++x)-- is essentially equivalent to x+1 but completely avoids having to call operator+, which can be quite useful sometimes.
So why is the precedence not defined to have ++x++ automatically expand to (++x)++ rather than ++(x++)? Is there some hidden meaning to the latter which I don't understand, or is it just to keep the precedence a simple list with all prefix operators making up one single level?
EDIT Ok, I didn't explicitly say it, but: of course I meant x to be user-defined type. For built-in types, (x+=2)-1 is of course better than (++x)++, and x+1 is a lot better than (++x)--. The situation that I have in mind is an iterator to a rather complicated type of semi-associative container, where operators += and + (being designed for random access) have to rebuild a cache in order to work efficiently for general requests, and are therefore an order of magnitude slower than ++. But of course I can modify them to always check first if the argument is a very small integer, and in that case just call operator++ repeatedly instead of doing the random-access procedure. That should work fine here, though I could imagine I might at some point have a situation in which I want operator+= to always go the random-access way, regardless of how small numbers I present it.
So... for me, I would conclude the answer to be:
the advantage of having a simple and well-memorizeable precedence list in which all postfix operators come before any of the prefix operators is sufficient to tolerate the minor drawback of always having to use parentheses to compose pre- and postfix operators ++/--, as this composition is used very seldom.
The simpler "C does it this way", while it seems likely to be the real reason, is far less satisfying in to me, because since ++x++ was not allowed at all in C it would have been possible to redefine this very composition without damaging any existing code.
Anyway, I will go on using (++x)--, as the parentheses really do not hurt so much.
(++x)++ increments x by two and returns the value "in the middle"
Why not (x += 2) - 1 or (++x, x++)? Both seem to be clearer. For scalars, both are well-defined also in C++03, as opposed to your proposed expression.
(++x)-- is essentially equivalent to x+1 but completely avoids having to call operator+, which can be quite useful sometimes.
That's an arbitrary statement without any explanation. So I'm going to throw into the pool:
x+1 is essentially equivalent to (++x)-- but completely avoids having to call operator++ and operator-- which can be useful sometimes.
So why is the precedence not defined to have ++x++ automatically expand to (++x)++ rather than ++(x++)
Just to make such arcane corner cases not error out? No way. Can you please recite man operator for me? If you cannot do that, better not try and write ++x++ in your code.
C++ standard just kept the C rules and obviously those weren't fixed considering operator overloading and idioms yet be invented in a yet to be invented language.
Looking at what is available in D.M. Ritchie Home Page, on see that this precedence is already present in B (Unary operators are bound right to left. Thus -!x++ is bound -(!(x++)) in Users' Reference to B) and I didn't see increment operators in BCPL.
Both (++x)++ and (++x)-- invoke undefined behaviour [assuming x to be a primitive type]. For user defined type the scenario would be different. However it is not generally recommended to use such confusing expressions in your code.
As far as the precendence is concerned this answer explains why post increment has higher precedence than pre increment.

An explanation about Sequence points

Lately, I have seen a lot of questions being asked about output for some crazy yet syntactically allowed code statements like like i = ++i + 1 and i=(i,i++,i)+1;.
Frankly realistically speaking hardly anyone writes any such code in actual programing.To be frank I have never encountered any such code in my professional experience. So I usually end up skipping such questions here on SO. But lately the sheer volume of such Q's being asked makes me think if I am missing out some important theory by skipping such Q's. I gather that the such Q's revolve around Sequence points. I hardly know anything about sequence points to be frank and I am just wondering if not knowing about it is a handicap in some way. So can someone please explain the theory /concept of Sequence points, or If possible point to a resource which explains about the concept. Also, is it worth to invest time in knowing about this concept/theory?
The simplest answer I can think of is:
C++ is defined in terms of an abstract machine. The output of a program executed on the abstract machine is defined ONLY in terms of the order that "side effects" are performed. And Side effects are defined as calls into IO library functions, and changes to variables marked volatile.
C++ compilers are allowed to do whatever they want internally to optimize code, but they cannot change the order of writes to volatile variables, and io calls.
Sequence points define the c/c++ program's heartbeat - side effects before the sequence point are "complete" and side effects after the sequence point have not yet taken place. But, side effects (or, code that can effect a side effect indirectly( within a sequence point can be re-ordered.
Which is why understanding them is important. Without that understanding, your fundamental understanding of what a c++ program is (And how it might be optimized by an agressive compiler) is flawed.
See http://en.wikipedia.org/wiki/Sequence_point.
It's a quite simple concept, so you don't need to invest much time :)
The exact technical details of sequence points can get hairy, yes. But following these guideline solves almost all the practical issues:
If an expression modifies a value, there must be a sequence point between the modification and any other use of that value.
If you're not sure whether two uses of a value are separated by a sequence point or not, break up your code into more statements.
Here "modification" includes assignment operations on the left-hand value in =, +=, etc., and also the ++x, x++, --x, and x-- syntaxes. (It's usually these increment/decrement expressions where some people try to be clever and end up getting into trouble.)
Luckily, there are sequence points in most of the "expected" places:
At the end of every statement or declaration.
At the beginning and end of every function call.
At the built-in && and || operators.
At the ? in a ternary expression.
At the built-in , comma operator. (Most commonly seen in for conditions, e.g. for (a=0, b=0; a<m && b<n; ++a, ++b).) A comma which separates function arguments is not the comma operator and is not a sequence point.
Overloaded operator&&, operator||, and operator, do not cause sequence points. Potential surprises from that fact is one reason overloading them is usually discouraged.
It is worth knowing that sequence points exist because if you don't know about them you can easily write code which seems to run fine in testing but actually is undefined and might fail when you run it on another computer or with different compile options. In particular if you write for example x++ as part of a larger expression that also includes x you can easily run into problems.
I don't think it is necessary to learn all the rules fully - but you need to know when you need to check the specification, or perhaps better - when to rewrite your code to make it so that you aren't relying on sequence points rules if a simpler design would work too.
int n,n_squared;
for(n=n_squared=0;n<100;n_squared+=n+ ++n)
printf("%i squared might or might not be %i\n",n,n_squared);
... doesn't always do what you think it will do. This can make debugging painful.
The reason is the ++n retrieves, modifies, and stores the value of n, which could be before or after n is retrieved. Therefore, the value of n_squared isn't clearly defined after the first iteration. Sequence points guarantee that the subexpressions are evaluated in order.