SovranCode
Modern C++ Lesson 09
Course contents50 available · 0 planned

Get a program running

01 · C++ Introduction: What Is C++?02 · How to Install a C++ Compiler and Set Up Your Editor03 · C++ Hello World: Your First Program Explained04 · How to Compile and Run C++ Programs05 · C++ Debugging: Warnings and Breakpoints

Work with values and input

06 · C++ Variables: Initialization and Scope07 · C++ Data Types: int, double and Type Conversion08 · C++ const, constexpr and auto Explained09 · C++ Operators: Arithmetic, Comparison and Logic10 · C++ User Input: cin, getline and Validation

Control flow and functions

11 · C++ Conditions: if, else if and else12 · C++ Switch Statement: Cases, break and default13 · C++ For Loop: Syntax and Examples14 · C++ While and Do-While Loops: Examples15 · C++ Functions: Parameters and Return Values

Strings and sequences

16 · C++ Strings: std::string with Examples17 · C++ Vector: std::vector with Examples18 · C++ Arrays: std::array and Bounds Checking19 · C++ Range-Based For Loop and Iterators20 · C++ Vector Practice: Build a Data Summary

Model data with classes

21 · C++ Structs and enum class Explained22 · C++ Classes and Objects: Encapsulation23 · C++ Constructors and Member Initialization24 · C++ Const Member Functions and Composition25 · C++ Copying Objects and the Rule of Zero

Lifetime and resource ownership

26 · C++ Object Lifetime, Destructors and RAII27 · C++ Pointers and References: nullptr and Borrowing28 · C++ unique_ptr: Smart Pointers and Ownership29 · C++ Move Semantics: std::move vs Copying30 · C++ string_view and span: Avoid Dangling Views

Containers and algorithms

31 · C++ map vs unordered_map: Lookup and Examples32 · C++ set, queue and stack: When to Use Each33 · C++ Lambda Expressions and STL Algorithms34 · C++ sort and binary_search: Rules and Complexity35 · C++20 Ranges: Views, filter and transform

Errors, files, and interfaces

36 · C++ optional and variant Explained37 · C++ Exceptions: try, catch and Safe Cleanup38 · C++ File Handling: Read and Write Text Files39 · C++ Input Parsing and Data Validation40 · C++ Polymorphism: Virtual Functions and Interfaces

Generic programming and quality

41 · C++ Templates: Function and Class Examples42 · C++20 Concepts and Template Constraints43 · C++ Unit Testing: Normal and Boundary Cases44 · C++ Sanitizers: Find Memory and Undefined Behavior Bugs45 · C++ Performance: Benchmark Before Optimizing

Build and deliver a complete application

46 · C++ Header Files and Translation Units47 · C++ CMake Tutorial: Build an Executable48 · C++ Dependencies and CTest: Automated Tests49 · C++ Multithreading: Threads and Data Races50 · C++ Command-Line Applications: Help and Release Checks
Modern C++50 available · 0 planned

Get a program running

01 · C++ Introduction: What Is C++?02 · How to Install a C++ Compiler and Set Up Your Editor03 · C++ Hello World: Your First Program Explained04 · How to Compile and Run C++ Programs05 · C++ Debugging: Warnings and Breakpoints

Work with values and input

06 · C++ Variables: Initialization and Scope07 · C++ Data Types: int, double and Type Conversion08 · C++ const, constexpr and auto Explained09 · C++ Operators: Arithmetic, Comparison and Logic10 · C++ User Input: cin, getline and Validation

Control flow and functions

11 · C++ Conditions: if, else if and else12 · C++ Switch Statement: Cases, break and default13 · C++ For Loop: Syntax and Examples14 · C++ While and Do-While Loops: Examples15 · C++ Functions: Parameters and Return Values

Strings and sequences

16 · C++ Strings: std::string with Examples17 · C++ Vector: std::vector with Examples18 · C++ Arrays: std::array and Bounds Checking19 · C++ Range-Based For Loop and Iterators20 · C++ Vector Practice: Build a Data Summary

Model data with classes

21 · C++ Structs and enum class Explained22 · C++ Classes and Objects: Encapsulation23 · C++ Constructors and Member Initialization24 · C++ Const Member Functions and Composition25 · C++ Copying Objects and the Rule of Zero

Lifetime and resource ownership

26 · C++ Object Lifetime, Destructors and RAII27 · C++ Pointers and References: nullptr and Borrowing28 · C++ unique_ptr: Smart Pointers and Ownership29 · C++ Move Semantics: std::move vs Copying30 · C++ string_view and span: Avoid Dangling Views

Containers and algorithms

31 · C++ map vs unordered_map: Lookup and Examples32 · C++ set, queue and stack: When to Use Each33 · C++ Lambda Expressions and STL Algorithms34 · C++ sort and binary_search: Rules and Complexity35 · C++20 Ranges: Views, filter and transform

Errors, files, and interfaces

36 · C++ optional and variant Explained37 · C++ Exceptions: try, catch and Safe Cleanup38 · C++ File Handling: Read and Write Text Files39 · C++ Input Parsing and Data Validation40 · C++ Polymorphism: Virtual Functions and Interfaces

Generic programming and quality

41 · C++ Templates: Function and Class Examples42 · C++20 Concepts and Template Constraints43 · C++ Unit Testing: Normal and Boundary Cases44 · C++ Sanitizers: Find Memory and Undefined Behavior Bugs45 · C++ Performance: Benchmark Before Optimizing

Build and deliver a complete application

46 · C++ Header Files and Translation Units47 · C++ CMake Tutorial: Build an Executable48 · C++ Dependencies and CTest: Automated Tests49 · C++ Multithreading: Threads and Data Races50 · C++ Command-Line Applications: Help and Release Checks
PREVIOUS LESSONC++ const, constexpr and auto Explained
NEXT LESSONC++ User Input: cin, getline and Validation
C++ foundations · Lesson 09 About 50 min with practice

C++ Operators: Arithmetic, Comparison and Logic

Read C++ arithmetic, comparison and logical operators. Trace precedence, integer quotient and remainder, short-circuit safety and named conditions with boundary tests.

Before you begin

Understand int, double and initialized values. Integer arithmetic practice runs in the browser; bool, comparisons, short-circuiting and branches require a local compiler.

What you will learn

  • Distinguish arithmetic, assignment and comparison.
  • Use parentheses to express intentional grouping.
  • Translate a requirement into named Boolean conditions.
  • Explain built-in && and || short-circuiting.
  • Test exact boundaries and protect unsafe operations.

An expression computes a value, not a requirement

An expression combines operands and operators to produce a value, and some expressions also have effects. A requirement such as 'delivery is allowed inside the area when the order qualifies' is not yet a C++ expression. First identify the facts, units and decisions. Then select operations that match them. This avoids writing a compact formula whose punctuation is valid but whose policy is different from the one you intended.

Arithmetic operators include addition, subtraction, multiplication, division and integer remainder. Comparisons such as <, <=, == and != produce bool values. Assignment uses = to update an object; equality uses == to compare values. Confusing the two can turn a condition into a state change. Keep comparisons and updates separate while learning, and enable warnings so the compiler can flag suspicious expressions without pretending warnings prove the business rule.

The same symbol can have different meanings in different contexts. << inserts values when used with std::cout; for integer operands it is a bit-shift operator. This lesson uses stream insertion only for output and postpones bit manipulation. Similarly, a minus sign can negate one operand or subtract two operands. Read an operation together with its operands and types rather than assigning one universal meaning to each character.

Delivery eligibility groups an in-area requirement with either a qualifying order or membership. The AND gate requires both sides; the OR gate accepts either qualifying fact. Parentheses preserve this stated policy.
Translate the policy first: in area AND (qualifying order OR membership).

Grouping changes the calculation

Multiplication, division and remainder bind more tightly than addition and subtraction. Thus 2 + 3 * 4 means 2 + (3 * 4), producing fourteen, while (2 + 3) * 4 produces twenty. Parentheses document a deliberate grouping and can make a policy easier to read even when precedence already produces the intended result. They do not compensate for incorrect units or an inappropriate operand type.

For nonnegative counts, quotient and remainder help distribute whole items into equal groups. Seventeen items in groups of five produces three complete groups and two remaining items. State that the group size must be positive before evaluating either operation. Negative operands have different interpretation concerns, and integer overflow remains possible even when the operators are familiar. The examples use small validated values so the arithmetic contract is visible.

Compound assignment such as total += amount updates total using the operation. Increment and decrement also modify state. Their prefix and postfix forms differ in the value produced by the expression. Until a loop needs them, keep updates on separate statements and avoid reading and modifying the same object several times in one expression. Operator precedence describes parsing; it is not a general guarantee that every operand is evaluated left to right.

C++ PRACTICE RUNNER

Predict grouping and leftover items

Run these supported integer operations. Change items to zero or eighteen and predict the quotient and remainder before running.

#include <iostream>
int main() {
    const int items{17};
    const int groupSize{5};
    const int groups{items / groupSize};
    const int leftover{items % groupSize};
    std::cout << "Groups: " << groups << '\n';
    std::cout << "Leftover: " << leftover << '\n';
    std::cout << "Unparenthesized: " << 2 + 3 * 4 << '\n';
    std::cout << "Grouped: " << (2 + 3) * 4 << '\n';
    return 0;
}
TERMINAL OUTPUT
Predict the output, edit the source, then select Run code.

C++20 compiler runner: source and input are sent only when you press Run to this website's execution endpoint, not an external vendor. Local preview requires Docker and gcc:14; production requires a separately isolated execution service. Network is disabled; execution is limited to 3 seconds, compilation to 10 seconds, memory to 384 MB and output to 32 KB. Single-file programs only. Don't enter secrets. Edits reset on refresh; Copy your work to keep it.

Compare with the starter's expected output
Groups: 3
Leftover: 2
Unparenthesized: 14
Grouped: 20

After editing inputs, calculate a new prediction; this reference describes only the starter.

Name the conditions before combining them

A bool holds true or false. A comparison gives a Boolean result that can be named, such as const bool withinArea{distanceKm <= 10}. The name should describe what the result means, not restate punctuation. Naming conditions makes a complex decision reviewable one piece at a time. It also gives your debugger useful intermediate observations when the final answer is wrong despite a successful build.

Built-in && means both conditions must be true; || means at least one must be true; ! negates a Boolean condition. For our delivery policy, withinArea && (qualifyingOrder || member) requires the geographic rule regardless of membership. Without those parentheses, withinArea && qualifyingOrder || member groups differently because && binds more tightly than ||. A member outside the area could qualify under that changed policy. The code would compile while expressing the wrong requirement.

Do not translate a mathematical interval as 0 <= age <= 120. C++ evaluates the first comparison to a Boolean value, then compares that result with 120; it does not create the intended interval test. Write age >= 0 && age <= 120. Also distinguish && from &: the latter is not the logical short-circuit operator taught here. A familiar-looking mathematical notation or single-character shortcut can silently answer a different question.

C++ PRACTICE RUNNER

Trace a delivery eligibility rule

The member is outside the area, so eligibility must remain false. boolalpha prints readable true/false words instead of the default numeric form.

#include <iostream>
int main() {
    const int distanceKm{12};
    const int orderCents{1500};
    const bool member{true};
    const bool withinArea{distanceKm >= 0 && distanceKm <= 10};
    const bool qualifyingOrder{orderCents >= 2000};
    const bool eligible{withinArea && (qualifyingOrder || member)};
    std::cout << std::boolalpha;
    std::cout << "Within area: " << withinArea << '\n';
    std::cout << "Eligible: " << eligible << '\n';
    return 0;
}
TERMINAL OUTPUT
Predict the output, edit the source, then select Run code.

C++20 compiler runner: source and input are sent only when you press Run to this website's execution endpoint, not an external vendor. Local preview requires Docker and gcc:14; production requires a separately isolated execution service. Network is disabled; execution is limited to 3 seconds, compilation to 10 seconds, memory to 384 MB and output to 32 KB. Single-file programs only. Don't enter secrets. Edits reset on refresh; Copy your work to keep it.

Compare with the starter's expected output
Within area: false
Eligible: false

After editing inputs, calculate a new prediction; this reference describes only the starter.

Short-circuiting can protect a later operation

For built-in &&, the left operand is evaluated first. If it is false, the right operand is not evaluated. For built-in ||, a true left operand skips the right operand. This matters when the right side has a precondition. count != 0 && total / count > 2 avoids evaluating the division when count is zero. Reversing those operands defeats the guard because the unsafe operation would occur first.

Short-circuiting is not a substitute for a complete numeric safety analysis. A nonzero divisor alone does not make every signed integer division safe: the minimum signed value divided by minus one can be unrepresentable. Our small nonnegative counts avoid that additional case. State those bounds explicitly instead of claiming one comparison handles every possible int input. For a fractional threshold, choose floating-point operands intentionally rather than inheriting integer truncation.

Do not hide an essential state update on the right of a logical operator and assume it always occurs. The skip behavior is exactly what makes the guard useful. Named pure conditions are easier to test than a chain of assignments, increments and function calls with side effects. Overloaded operators on user-defined types have further rules; this lesson's short-circuit explanation applies to the built-in Boolean operators, not arbitrary classes with similarly named operations.

C++ PRACTICE RUNNER

Observe a skipped division

count is zero. The false left condition prevents evaluation of the integer division on the right. Run it in the compiler-backed editor or with your local compiler.

#include <iostream>
int main() {
    const int total{7};
    const int count{0};
    const bool aboveTwo{count != 0 && total / count > 2};
    std::cout << std::boolalpha << "Above two: " << aboveTwo << '\n';
    return 0;
}
TERMINAL OUTPUT
Predict the output, edit the source, then select Run code.

C++20 compiler runner: source and input are sent only when you press Run to this website's execution endpoint, not an external vendor. Local preview requires Docker and gcc:14; production requires a separately isolated execution service. Network is disabled; execution is limited to 3 seconds, compilation to 10 seconds, memory to 384 MB and output to 32 KB. Single-file programs only. Don't enter secrets. Edits reset on refresh; Copy your work to keep it.

Compare with the starter's expected output
Above two: false

After editing inputs, calculate a new prediction; this reference describes only the starter.

Test decisions with facts, not only one happy case

Create a small truth table in your notes: an order inside the area and above the threshold qualifies, an inside-area member with a smaller order qualifies, an inside-area nonmember with a smaller order does not, and an outside-area member does not. Those cases distinguish the intended policy from the unparenthesized alternative. Merely observing true for one large order would not expose the policy error.

Test distances nine, ten and eleven and order values 1999, 2000 and 2001. At the exact threshold, <= and >= include the boundary; < and > exclude it. Add zero and a negative distance as modeling cases rather than allowing nonsensical values by accident. Keep units consistent: comparing cents with a dollar threshold is a requirement error, not an operator-precedence problem. A review should connect each expression to one documented policy and one discriminating test.

LOCAL TERMINAL COMMANDS

Build and run the local examples

Save one complete example or lab solution as main.cpp. Choose your installed toolchain; run only after a successful build. Input examples wait for text in your terminal. The browser teaching interpreter does not support these full-language features.

macOS / Clang:
clang++ -std=c++20 -Wall -Wextra -Wpedantic main.cpp -o lesson
./lesson

Linux / GCC:
g++ -std=c++20 -Wall -Wextra -Wpedantic main.cpp -o lesson
./lesson

Windows Developer Command Prompt / MSVC:
cl /std:c++20 /EHsc /W4 main.cpp /Fe:lesson.exe
lesson.exe
APPLY THE CONCEPT

Independent lab

Implement the delivery eligibility expression for a nonmember exactly on the distance and order boundaries. Then test the four policy combinations.

Acceptance checklist

  • Use distanceKm 10, orderCents 2000 and member false.
  • Require a nonnegative distance no greater than ten.
  • Qualify an order at or above two thousand cents.
  • Keep the OR group parenthesized inside the area requirement.
  • Print Eligible: true and record tests for outside-area members and below-threshold nonmembers.
Need a hint?
  1. Write withinArea and qualifyingOrder first.
  2. Use boolalpha for the requested words.
  3. Change only one fact at a time around each threshold.
C++ PRACTICE RUNNER

Write and run your lab

Build your own solution before revealing the reference. Use the input field for normal, boundary and invalid cases; this runner executes your program but does not grade it.

#include <iostream>
#include <string>
#include <sstream>
#include <limits>

int main() {
    // Implement the acceptance checklist above.
    return 0;
}

TERMINAL OUTPUT
Predict the output, edit the source, then select Run code.

C++20 compiler runner: source and input are sent only when you press Run to this website's execution endpoint, not an external vendor. Local preview requires Docker and gcc:14; production requires a separately isolated execution service. Network is disabled; execution is limited to 3 seconds, compilation to 10 seconds, memory to 384 MB and output to 32 KB. Single-file programs only. Don't enter secrets. Edits reset on refresh; Copy your work to keep it.

Your lab evidence and notes

Record predictions, actual output, commands and the cause of each repair. Code is plain text: this scratchpad does not execute or grade C++.

Loading local notes…

Review your acceptance checklist and quiz explanations before marking this lesson complete. This is self-review, not a grade or certification.

Reveal the explained lab solution
C++ PRACTICE RUNNER

Reference lab solution

Compare the reference with your own reasoning. Running this solution does not grade or complete the lesson.

#include <iostream>
int main() {
    const int distanceKm{10};
    const int orderCents{2000};
    const bool member{false};
    const bool withinArea{distanceKm >= 0 && distanceKm <= 10};
    const bool qualifyingOrder{orderCents >= 2000};
    const bool eligible{withinArea && (qualifyingOrder || member)};
    std::cout << std::boolalpha << "Eligible: " << eligible << '\n';
    return 0;
}
TERMINAL OUTPUT
Predict the output, edit the source, then select Run code.

C++20 compiler runner: source and input are sent only when you press Run to this website's execution endpoint, not an external vendor. Local preview requires Docker and gcc:14; production requires a separately isolated execution service. Network is disabled; execution is limited to 3 seconds, compilation to 10 seconds, memory to 384 MB and output to 32 KB. Single-file programs only. Don't enter secrets. Edits reset on refresh; Copy your work to keep it.

Expected output

Eligible: true

Both numeric boundaries are inclusive. The starter qualifies without membership because its order meets the threshold.

Membership bypasses only the order threshold, not the area rule. Distance eleven must still produce false.

An inside-area nonmember with 1999 cents produces false. That case distinguishes >= from an accidentally lower threshold.

Review before moving on

Explain the lesson's objectives in your own words, compare your lab evidence with the acceptance checklist, and keep the first failing case alongside your repair. Completing a page is not proof that every C++ feature or input is supported.

  • Distinguish arithmetic, assignment and comparison.
  • Use parentheses to express intentional grouping.
  • Translate a requirement into named Boolean conditions.
  • Explain built-in && and || short-circuiting.
  • Test exact boundaries and protect unsafe operations.

References and further reading

Original examples and exercises accompany these primary references. Tool-specific diagnostics and support depend on your installed version.

  • C++ draft: logical AND
  • C++ draft: logical OR
  • C++ draft: multiplicative operators
KNOWLEDGE CHECK

Check your understanding

Answer all five questions, then review the explanations. Answers are not saved or synced; completion is a separate self-review choice.

01What does 2 + 3 * 4 produce?
02Which interval check means age is between zero and 120 inclusive?
03Why put count != 0 before a division in built-in &&?
04Which symbol compares equality?
05Which case best catches a member bypassing the area rule?
PREVIOUS LESSONC++ const, constexpr and auto Explained
NEXT LESSONC++ User Input: cin, getline and Validation
ON THIS PAGELearning objectivesAn expression computes a value, not a requirementGrouping changes the calculationName the conditions before combining themShort-circuiting can protect a later operationTest decisions with facts, not only one happy caseIndependent labReviewKnowledge checkReferences
Course overview