Mihai Bişog
Mihai Bişog

Reputation: 1018

The evaluation of 'if' expressions

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

Answers (5)

Ed Swangren
Ed Swangren

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

Jerry Coffin
Jerry Coffin

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

necromancer
necromancer

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

loganfsmyth
loganfsmyth

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

Qaz
Qaz

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

Related Questions