I've found this code is as an example of the usage of the comma-operator in a C++ book (C++ Primer, 5th Edition):
vector<int>::size_type cnt = ivec.size();
// assign values from size...1 to the elements in ivec
for(vector<int>::size_type ix = 0; ix != ivec.size(); ++ix, --cnt)
ivec[ix] = cnt;
I don't think that this is an appropriate example, because the order of evalation and side-effects don't matter here. The comma-operator just allows for separating the increment and decrement expressions, which is a common usage of the comma operator, but not the intention of this section in the book. A better example is shown at cppreference.com (please scroll down to the headline Built-in comma operator).
What is really on my mind is the following exercise:
Exercise 4.31 The program in this section used the prefix increment and decrement operators. Explain why we used prefix and not postfix. What changes would have to be made to use the postfix versions? Rewrite the program using the postfix operators.
There is no special reason to prefer the prefix over the postfix operators in this case. The evaluation order doesn't matter. The manipulation of objects with simple
type like vector<int>::size_type
shouldn't benefit from the usage of prefix over postfix in practice, so it's just a known convention to prefer prefix over postfix, in case the performance matters.
To give you the full context, here the section from the book:
4.10 Comma Operator
The comma operator takes two operands, which it evaluates from left to right. Like the logical AND and logical OR and the conditional operator, the comma operator guarantees the order in which its operands are evaluated.The left-hand expression is evaluated and its result is discareded. The result of a comma expressions is the value of its right-hand expression. The result is an lvalue if the right-hand operand is an lvalue. One common use for the comma operator is in a for loop:
vector<int>::size_type cnt = ivec.size(); // assign values from size...1 to the elements in ivec for(vector<int>::size_type ix = 0; ix != ivec.size(); ++ix, --cnt) ivec[ix] = cnt;
This loop increments ix and decrements cnt in the expression in the for header. Both ix and cnt are changed on each trip through the loop. As long as the test of ix succeeds, we reset the
nextcurrent element to the current value of cnt.
Am I right? Or do I just not get the purpose of this exercise?
You are right about using prefix or postfix increment operator doesn't matter in this example, but C++ Primer also says that only use postfix version when really necessary as a best practice, I'm quoting the book from §4.5. Increment and Decrement Operators
Advice: Use Postfix Operators only When Necessary
Readers from a C background might be surprised that we use the prefix increment in the programs we've written. The reason is simple: The prefix version avoids unnecessary work. It increments the value and returns the incremented version.The postfix operator must store the original value so that it can return the unincremented value as its result. If we don’t need the unincremented value, there’s no need for the extra work done by the postfix operator.
For
int
s and pointers, the compiler can optimize away this extra work. For more complicated iterator types, this extra work potentially might be more costly. By habitually using the prefix versions, we do not have to worry about whether the performance difference matters. Moreover—and perhaps more importantly—we can express the intent of our programs more directly.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With