c++ iterator stuck at first value - c++

I'm learning c++ and I've run into some behaviour that I can't explain. The two pieces of code below provide different results, while I would expect them to be equivalent:
success = true;
vector<instruction>::const_iterator i;
for (i = instructions.begin(); i != instructions.end(); ++i) {
bool up = update(*i);
success = success && up;
}
and
success = true;
vector<instruction>::const_iterator i;
for (i = instructions.begin(); i != instructions.end(); ++i) {
success = success && update(*i);
}
I have the impression that the second version always takes the initial value of the iterator. Could someone explain me the reason?

The two pieces of code are not equivalent.
The first one always calls update, while the second one will not. The reason is that && does something called short-circuit boolean evaluation. If success is false, the second half of the expression is not evaluated.
Note that you did not post what update is or what is returned. Therefore we can only assume what may be able to be returned from update, which is either going to be true or false.
If you wanted update to always be called, it should be placed first in the && expression.

The operator && will not evaluate the right hand side if the result is computable with just the left hand side value. We call this short-circuiting.
Once success is false, update(*i) will no longer be called.
Aside from your first block of code (which always calls update(*i)), one fix is to use the operator & instead which always evaluates both arguments. Another fix is to write
success = update(*i) && success;
But that's vulnerable to recalcitrant refactoring. Better still, use
success &= update(*i);
But be aware of this comment by #Angew:
Using &= in a boolean context is dangerous. What if update now (or after a future refactoring) returns an int with the semantics "non-zero for true" (cf. isdigit and friends)? Remember that bool(true & 2) is false.

Related

Ternary Operator Not Generating Error

I've been familiar with the ternary operator for quite some time now, and have worked with it in a few differnet languages. My understanding of the operator is this:
condition ? expr1 : expr2
However, in C++, the following code is legal:
int i = 45;
(i > 0) ? i-- : 1;
Aren't you, in effect, just writing 1; or i - 1;How is this a complete statement? I understand that the intention of the code is to decrement i if it's greater than 0, but I would've thought that the code would generate a compiler error as just being an expression, not a full statement. I expected code like this:
int i = 45;
i = (i > 0) ? i - 1 : i;
This is called expression statement. The expression is evaluated and its value is discarded.
Even this is valid:
42;
although it does nothing. Only side effects (like i--, assignment, etc) in the expression have effects.
In fact, many statements we use are expression statements: assignments, function calls, etc:
a = 42;
foo();
That is a valid expression. You might have received a warning because you are not saving the result of the expression, but that you have the i-- your statement does have an effect.
In C++, an expression like 1 is a perfectly valid statement with no side effects. You could very feasibly write this function:
void f() {
1;
}
In fact, even this is correct.
void f() {
;;;;
}
A literal statement evaluates its arguments but does nothing more. The system views 1; as being just like func();. The only difference is that while func(); would logically have some side effects, 1; does not so it ends up being a no-op. The ternary operator evaluates like an if-statement, so the second form is only evaluated if the operand is true. Thus:
(i > 0) ? i-- : 1;
If i is greater than 0, the second form is evaluated. When it is evaluated, it carries its side effect, which decrements i by 1. Otherwise, the third form is evaluated, which does nothing. Although this block of code works, it is not incredibly readable, so while it's nice toy code a real if-statement is ideal for situations like this. For the same reason, this line would have the same effect but be frowned upon for being equally unreadable.
((i > 0) && (i--)) || 1;
Assuming you didn't overwrite the boolean operators, this code will short-circuit and behave like the ternary operator. If i is not greater than 0, then the && need not evaluate its second operand since the && is false, but the || must since it might be true. Inversely, if i is greater than 0, the && needs to evaluate but the || already knows it's true.
Aren't you, in effect, just writing 1; or i - 1;
No: i-- is not the same as i - 1. In the first case, the value of i is modified. In the second case it is not.
In the event that i less than or equal to zero, then you're correct that the resulting 'code' will be 1. However, the compiler will realise that this is not a useful thing to execute and so it ought to generate code equivalent to:
if( i > 0 ) i--;
Some (including myself) would consider that using the ternary operator in this fashion is bad style. Just for fun, here's another way someone might write it that's also not very nice (also more likely to generate compiler warning):
i > 0 && i--;
In the end, style is a matter of preference. The compiler, for the most part, will decide the best way to turn your code into assembly. So you owe it to yourself to write code that is clear and concise.

breaking up conditional expression

I'm trying to evaluate if there's a performance hit in writing this expression
bool func() {
if (expr1 || expr2 ... || exprN)
return 1;
return 0;
}
as
bool func() {
if (expr1)
return 1;
if (expr2)
return 1;
...
if (exprN)
return 1;
return 0;
}
The reason I'm trying to do the latter is simply to improve readability/maintainability (eg. latter can be written in terms of a helper macro and thereby making it easier to add/remove exprs. There are about 50 expressions in this case).
A similar scenario is writing
bool func() {
if (expr1 && expr2 && ... && exprN) {
return 1;
}
return 0;
}
as
bool func() {
if (!expr1) {
return 0;
}
if (!expr2) {
return 0;
}
...
if (!exprN) {
return 0;
}
return 1;
}
Is there a performance hit in this case and if so do compilers optimize try to optimize it? I'd be interested to know if gcc does that.
(To give some context the expressions themselves are functions and let's say we want to determine if all or at least one returns true. The functions take arguments of different types)
Your two versions are functionally equivalent.
In C/C++ (and many other languages) the logical operators || and && perform "short-circuit" evaluation. They evaluate the sub-expressions from left to right, stopping as soon as the result is known. In the case of ||, this means it stops as soon as it gets a true (non-zero) result (because true || anything is true); in the case of &&, it stops as soon as it gets a false (zero) result (because false && anything is false).
If you were performing any other actions in your if bodies other than just returning from the function, it would be duplicated for every expression that's true. But since you're returning from the function as soon as one of the expressions is true, you'll never test any of the remaining expressions. So it's doing the same short-circuiting.
If you did have some action in the body, you could get the same type of short-circuiting by using else if rather than if. However, this would violate the DRY principle. But if it's in the output of a macro, rather than the original source code, this wouldn't be a signficant concern (although it would likely increase the size of the generated code -- if taken to extremes this could have memory performance implications).
Your current code
bool func() {
if (expr1 || expr2 ... || exprN)
return 1;
return 0;
}
involving umpteen logical expressions, can be written as the possibly more clear & maintainable
auto func()
-> bool
{
return false
|| expr1
|| expr2 ...
|| exprN;
}
This allows the compiler the best opportunity to optimize, because it's presented with complete information about the desired effect.
In contrast, a series of individual if statements would have to be analyzed by the compiler to determine that they implement an OR-chain.
As always when in doubt about micro-performance, MEASURE.
The C and C++ codes are generated to its assembly equivalent.
Hence, what i think is that the code generated should not be different unless you have multiple output function or jump statements(including Return, like you have in your second example).
So i think there should be no performance hit unless you have too many jumps in your improved readability code.

not able to understand return statement in isEmpty function of stack implementation

I have isEmpty() function in my stack. And it looks something like below.
bool Mystack<T>::isEmpty() const //function 1
{
if(top==-1)
return true;
else
return false;
}
I saw a couple of online code for isEmpty(), which I could not understand. Below is the snippet.
bool Mystack<T>::isEmpty() const //function 2
{
return top == -1;
}
Question 1: Are both the functions doing the exactly the same task?
Question 2: If yes, then can some one please explain how the syntax in function 2 performing its task without using any if statement.
top == -1 is an expression. Assuming no operator overloads are involved, its return type is bool. It will have the value true if top equals -1 and the value false if that's not the case.
return top == -1; means "return the value of the expression top == -1". As I've shown above, this value is either true or false. These coincide exactly with the values returned from the if()-based code, so the two codes are equivalent.
In my code, I tend to use parentheses around "syntactically unusual" return statements, and I consider == one of them. So I would write this in my code (and I would certainly prefer it to the if version):
return (top == -1);
Yes, both functions work exactly the same. They return whether top equals -1.
In the first code, this is written somewhat "explicitly" (from the reader's perspective). Its English equivalent would be (roughly):
Evaluate the expression top == -1.
If the result is true, then return true, else return false.
The second code does it more subtly, and its rough English equivalent would be:
Return the result of the expression top == -1.
Yes, they do exactly the same thing.
Think about the semantics of an if statement. The condition evaluates to a bool and is checked against true. top==-1 will either evaluate to true or false, if it evaluates to true then the first form is executed and true is returned, otherwise the second form is evaluated and false is returned. This is exactly the same as the second version, just more verbose.
Answer 1: Yes, same task.
Answer 2: I have no exact idea of c++, but logically
return top == -1;
can be broken into
check if the value of top is equal to 1 or not.
1.1 if equal, return 1 [or TRUE] (as a result of comparison success)
1.2 if not, return 0 [or FALSE] (as a result of comparison failure)
As reference, from C99 standard document, chapter 6.8.6.4, paragraph 3,
If a return statement with an expression is executed, the value of the expression is
returned to the caller as the value of the function call expression.
and for that of c++11, chapter 6.6.3, paragraph 2,
. . . A return statement with an expression of non-void type can be used only in functions returning a value; the value of the expression is returned to the caller of the function....

Short circuit recursion

Is it possible to do the following without getting a stackoverflow?
int foo(int i = 0)
{
return foo(--i) || i;
}
When foo(--i) evaluates to 0, it should return false, therefore returning i and ending the execution.
You want return !i || foo(--i).
Note that || is short-circutted. This means that evaluation (which is performed from left to right) will continue for only as long as the result of the expression is not known. So the way I've written it, the case i being zero will block the recursion.
(Moving on to more advanced issues, you need to be very careful when evaluating expressions when the same variable appears in more than one sub-expression and it's value is changed in some of them. My having !i and --i could get me in trouble: I'm not too far away from undefined behaviour here. In fact, it turns out that my code is completely safe since || is a sequence point and the order of evaluation with || is well-defined. But do be careful.)
From what you have coded foo never returns because it will continuosly go on decreasing i and recurse. You need a check inside foo which returns whatever you want when you get i as 0.

How is it breaking out of the for loop in this C++ code?

Here is the code:
for (int i=0;i<someClass::someList.entries();i++)
returnBool |= (someOtherClass.get_something() ==
((someClass*)(someClass::someList[i]))->get_something_else());
What I think it does, it iterates through all instance i.e. ptr of someClass held in someList. and if get_something() == get_something_else() then we assign value 1 to returnBool, otherwise 0 as its a bitwise OR operator.
However in debugger what I'm noticing is that, regardless of how long someList is, it is breaking out of the for loop as soon as returnBool is 1 - does that sound right?
Thanks for your time =]
Actually, as soon as returnBool is true, no amount of |= will make it false, because true | false == true.
You can actually safely break from the loop the first time returnBool is true (unless the methods get_something are mutating, which, by their name, are not).
Probably a compiler optimization. I assume that these functions were simple enough that it could see that they have no side-effects.
If you are sure that you can skip them, I suggest making this optimization more visible and mandatory for other less smart compiler (or human):
for (int i=0;i<someClass::someList.entries() && !returnBool;i++)
returnBool |= (someOtherClass.get_something() ==
((someClass*)(someClass::someList[i]))->get_something_else());
Alternatively, if the compiler was wrong (unlikely) or you wish to make clear that you want to test the whole list, just do this:
for (int i=0;i<someClass::someList.entries();i++)
returnInt += (someOtherClass.get_something() ==
((someClass*)(someClass::someList[i]))->get_something_else());
return returnInt > 0;