Reputation: 1018
Consider I have the following:
edge some_edge;
std::priority_queue<edge> my_queue;
Is it safe to write such an 'if' even if the queue might be empty?
if ((my_queue.size() > 0) && (my_queue.top().weight < some_edge.weight)) {
do_something;
}
What about this one?
if ((my_queue.top().weight < some_edge.weight) && (my_queue.size() > 0)) {
do_something;
}
Does evaluating an expression in which 'and' is the operator between the operands stop if the left operand evaluates false?
Upvotes: 2
Views: 164
Reputation: 124790
An if
statement in C++ is left to right associative and the logical boolean operators &&
and ||
are short circuiting, so yes, a statement like the following is safe because it is guaranteed that you check the size first (assuming no evil overloading of these operators):
if(myqueue.size() > 0 && myqueue.top().whatever) {
// ...
}
The reverse is not true however because you check the return value of size()
after popping the queue.
As an aside, std::priority_queue
provides an empty()
function that I/many would prefer over size() > 0
, but that works too.
if(!myqueue.empty() && myqueue.top().whatever()) {
// ...
}
Upvotes: 4
Reputation: 490728
This really isn't about if
at all, it's about &&
. The logical operator (both &&
and ||
) evaluate their left operand first. Then if and only if the right operand could affect the logical result, they evaluate the right operand.
In the case of &&
, if the left operand evaluates to false
, the result will be false
regardless of the right operand's value, so the right operand will not be evaluated.
In the case of ||
, if the left operand evaluates to true
, the result will be true
regardless of the right operand's value, so the right operand will not be evaluated.
This is true whether the &&
is in the expression of an if
statement or not. Some obfuscated code makes use of this by turning if (x) y;
into x && y
. Though not see as often, you can do the same with ||
as well.
Upvotes: 2
Reputation: 24651
This link explains how this is not true for all operators, even though it is true for &&. In particular, note the difference between left-to-right/right-to-left in the context of associativity versus order of evaluation. http://en.cppreference.com/w/cpp/language/eval_order
Upvotes: 1
Reputation: 161657
Boolean expressions are short-circuit evaluated, so if the first part fails, the second will not run. So the first example will not access nonexistant memory, but the second one will.
Upvotes: 0
Reputation: 61970
Yes, this behaviour is guaranteed per the C++ standard.
if (false && doSomething())
will never evaluate doSomething()
.
However, if you overload operator&&
, all expressions are evaluated so this behaviour could differ. This is why it's a bad idea to touch operator&&
.
You should use !empty()
instead of size() > 0
though.
Upvotes: 4