Short-circuit Evaluation

Learn how the && and || operators are optimized with short-circuit evaluation, only evaluating expressions when necessary

Ryan McCombe
Published

When we combine boolean values using the AND (&&) and OR (||) operators, C++ and most other programming languages are smart about how it evaluates them. It performs what's known as short-circuit evaluation.

This means that the second operand in a logical expression is only evaluated if its value is absolutely necessary to determine the final result. We'll walk through some examples in this lesson.

This short-circuiting behavior is not just a performance optimization - we can also use it to control the flow of our code, much like we'd use if and else statements.

For example, imagine we have two tasks that must be performed in sequence, but the second task should only be attempted if the first one succeeds. We could write this using an if statement, which works perfectly fine:

#include <iostream>
using namespace std;

bool TaskOne() {
  cout << "Performing task one...\n";
  // ...
  cout << "Something went wrong!\n";
  return false;
}

bool TaskTwo() {
  cout << "Performing task two...\n";
  // ...
  cout << "Success!\n";
  return true;
}

int main(){
  bool TaskOneComplete{TaskOne()};
  if (TaskOneComplete) {
    TaskTwo();
  }
}
Performing task one...
Something went wrong!

However, by using the short-circuiting behavior of the && and || operators, we can write sequential dependencies like this in a much simpler way.

Example 1: Using &&

In an expression like TaskOne() && TaskTwo(), if TaskOne() evaluates to false, TaskTwo() is never evaluated, meaning TaskTwo is not invoked.

The reason for this is that it doesn't matter what TaskTwo() returns - it is not going to change the value returned by the && operator.

After TaskOne() returns false, the expression is equivalent to false && TaskTwo(). The expression false && anything will return false regardless of the value of anything, so our program won't even check what anything is.

The following program shows this in action:

#include <iostream>
using namespace std;

bool TaskOne() {/*...*/}
bool TaskTwo() {/*...*/} int main(){ bool TasksCompleted{TaskOne() && TaskTwo()}; if (!TasksCompleted) { cout << "Failed to complete the tasks"; } }

Note how TaskTwo() isn't executed if TaskOne() returns false:

Performing task one...
Something went wrong!
Failed to complete the tasks

We can extend this pattern to any number of evaluations. The following expression will continue until one of the tasks returns false:

bool TasksCompleted{
  TaskOne() &&
  TaskTwo() &&
  TaskThree() &&
  TaskFour()
};

Test your Knowledge

Short-Circuit Evaluation

What will the following program log out?

#include <iostream>
using namespace std;

bool ShouldLog(int x) {
  return x > 5;
}

int main(){
  int Value{3};
  ShouldLog(Value) && cout << Value;
}

Example 2: Using ||

The same logic applies to the || operator. It doesn't evaluate operands unnecessarily - as soon as knows the result of the overall expression, it returns it.

This means that, in an expression like OptionOne() || OptionTwo(), if OptionOne() returns true, OptionTwo() is never evaluated.

This is because it doesn't matter what OptionTwo() will return - if OptionOne() was true, the overall expression is going to be true. In other words, true || anything is true regardless of the value of anything.

In the following example, we provide two options to complete a task. The program will stop as soon as it finds one that works:

#include <iostream>
using namespace std;

bool OptionOne() {
  cout << "Trying option one...\n";
  // ...
  cout << "Success!\n";
  return true;
}

bool OptionTwo() {
  cout << "Trying option two...\n";
  // ...
  cout << "Success!\n";
  return true;
}

int main(){
  bool WorkDone{OptionOne() || OptionTwo()};
  if (WorkDone) {
    cout << "Work completed successfully";
  }
}

Note how OptionTwo() isn't called if OptionOne() returns true:

Trying option one...
Success!
Work completed successfully

Summary

In this lesson, we've learned about short-circuit evaluation, a key feature of logical operators that makes our code more efficient and concise.

  • && (AND) stops evaluating as soon as it finds a false operand. The expression A && B will not evaluate B if A is false.
  • || (OR) stops evaluating as soon as it finds a true operand. The expression A || B will not evaluate B if A is true.
  • Benefits: This behavior allows us to write more performant code by avoiding unnecessary function calls, and gives us a concise way of creating sequential conditions in a single expression.
Next Lesson
Lesson 21 of 61

Abstraction and Classes

Learn how to define, instantiate, and utilize classes, understanding how they form the backbone of object-oriented programming.

Have a question about this lesson?
Answers are generated by AI models and may not be accurate