Tutorials Logic, IN info@tutorialslogic.com

C++ Variables, const, constexpr, auto, and Useful Comments

Names, Values, and Intent

A variable gives a typed object a name and lifetime. Initialize it where it is declared so every later read has a known value. Use const when code must not modify an object through that name, and constexpr when a value or function must be usable during constant evaluation.

auto asks the compiler to deduce a type from the initializer; it does not make C++ dynamically typed. Use it when the type is obvious or cumbersome, but spell out a domain type when deduction would hide units, signedness, ownership, or an important conversion.

Initialization and Mutability

Brace initialization rejects many narrowing conversions. const protects an initialized runtime value from later assignment, while constexpr requires a constant-expression initializer and implies const for an object.

Calculate a constexpr conversion

Calculate a constexpr conversion
#include <iostream>

constexpr int minutes_to_seconds(int minutes) {
    return minutes * 60;
}

int main() {
    constexpr int timeout = minutes_to_seconds(3);
    const auto retries = 2;
    std::cout << timeout << " seconds, " << retries << " retries\n";
}
Output
180 seconds, 2 retries

timeout is available during constant evaluation; retries is deduced as int and cannot be reassigned.

Comments That Survive Refactoring

A useful comment records why a rule exists, the unit of a value, an external protocol constraint, or a non-obvious tradeoff. Comments that merely translate syntax become stale when code changes. Prefer names such as timeout_seconds over comments that repeatedly explain units.

  • Comment decisions and invariants, not punctuation.
  • Remove commented-out code; version control already preserves history.
  • Use TODO only with an owner or issue reference.

Express Mutability in the Declaration

Use const for values that must not change and keep the changing state narrowly scoped.

Express Mutability in the Declaration
#include <iostream>

int main() {
    const int retry_limit{3};
    int attempts{0};
    while (attempts < retry_limit) {
        ++attempts;
    }
    std::cout << attempts << '/' << retry_limit << '\n';
}
Output
3/3
  • Brace initialization makes narrowing mistakes visible; const documents the invariant.
Before you move on

Declaration Review

5 checks
  • Every variable is initialized.
  • Mutability is intentional.
  • auto does not hide a meaningful domain type.
  • constexpr is used only where constant evaluation matters.
  • Comments explain durable context.

Declaration Failures

  • Uninitialized local value

    Initialize at declaration; reading an indeterminate value can produce undefined behavior.
  • auto drops a reference

    Use auto& or const auto& when deduction must preserve reference semantics.

Variable Questions

<code>auto value = 1;</code> infers <code>int</code>, while some braced forms can infer <code>std::initializer_list<int></code>. That changes overload resolution and assignment behavior.

<code>const</code> prevents modification after initialization, but its value may still come from runtime input. <code>constexpr</code> requires an initializer that can be evaluated at compile time and is appropriate for template arguments and other constant-expression contexts.

A useful comment records an invariant, a non-obvious trade-off, a protocol requirement, or why a tempting alternative is unsafe. A comment such as “increment i” beside <code>++i</code> adds noise and can become stale.

Next Step
Next Practice

Finish the concept here, then reinforce it with hands-on coding, interview prep, or a tool that matches the topic.

Browse Free Tutorials

Explore 500+ free tutorials across 20+ languages and frameworks.