Concepts / Declaring and Initializing Variables

Declaring and Initializing Variables

Every variable in a program needs a name, and the name is the first thing a reader uses to understand what the variable holds.

  • Programming

Why Building a String Can Be Expensive

Declaring a variable and initializing it looks like a small, mechanical task. Yet the way you write a declaration, and the name you give it, decide how easily another person can read the code later. This article starts with a surprising case that shows why these details matter. Building a string letter by letter with the statement str = str + ch looks harmless, but it creates a whole new String on every step, and each new String copies the old content. Before reading on, think about what that means for a long string.

What do you think happens?

When str = str + ch runs on a string that already holds many letters, what happens to the old content?

  • The old characters are simply extended in place, with no copying

  • A new String is created that copies the old content and then adds ch

  • Only the single character ch is stored, and the old content is discarded

Reveal answer
Answer:

A new String is created that copies the old content and then adds ch.

Because each assignment builds a whole new String, the copying work on each step includes everything built so far. The longer the string becomes, the more work each later step requires.

Anatomy of a Single Declaration

Every variable in a program needs a name, and the name is the first thing a reader uses to understand what the variable holds. A good name tells the reader what the value means. A poor name forces the reader to hunt through the code to find out. Because programs are read far more often than they are written, naming and declaration choices affect how easily code can be understood and maintained later.

A declaration introduces a name, gives that name a type, and can optionally give it an initial value. A single declaration therefore has three parts that a reader needs to find quickly: the type, the name, and the initial value. In a statement such as the one below, the type comes first, the name follows, and the braces hold the initial value. Once you can locate each part, you can tell at a glance what the variable is and what it starts with.

cpp
Notes on the code
  • int is the type, count is the name, and {0} holds the initial value
  • double is the type, price is the name, and {9.5} holds the initial value

The first guideline is to declare one name only in each declaration. C++ allows several names to share one declaration, but the guideline asks you not to use that form. The reason is that when several names share one declaration, the reader has to untangle which initial value belongs to which name. In the first form below, two names are introduced but the initializer appears only once at the end, so it is not obvious what the first name starts with. In the second form, each declaration is self-contained.

cpp
Notes on the code
  • Shared form: the reader must work out whether width also starts at zero
  • Preferred form: each name has its own declaration and its own initial value

Choosing Between Braces and the Equals Form

The source gives two initialization rules. For a declaration with a named type, prefer the braces form, in which curly braces surround the initial value. For a declaration that uses auto, prefer the equals form. The two rules work together. When the type is visible in the declaration, the braces form keeps the type and the value side by side. When auto is used, the type is not written out, so the equals form keeps the declaration short and readable. Applying both rules gives consistent declarations throughout a program.

Matching Name Length to Scope

The second group of guidelines ties the length of a name to how the variable is used. A local variable is used only inside a small region of code, such as a loop body or a single function. A nonlocal variable is visible across a wider part of the program. The guideline is to keep common and local names short, and to give uncommon and nonlocal names longer, more descriptive names. The diagram below shows the progression: as visibility widens, the name grows more descriptive, because a reader far from the declaration has less context to work from.

Whole programuncommon, nonlocal namesSingle functionmedium-length namesLoop bodyshort names such as icontainscontains
Which parts of the code can see a variable, and how a short name in a small scope differs from a long name in a wide scope

A loop index is the classic case of a common, local name. Readers expect a loop index to be named i, so a short conventional name is clearer than a long descriptive one. A long name there would add noise without adding information, because the loop's purpose is already obvious from the loop itself. By contrast, a variable visible across the whole program needs a name that tells a reader far from its declaration what the value means.

cpp
Notes on the code
  • The loop index i is short because it is common and local to the loop
  • square is a short local name whose meaning is obvious from the nearby code
  • quarterly_sales_total is a wider, longer name that a distant reader can still understand

What Happens When a String Grows

Recall the statement from the opening. Each time str = str + ch runs, the program builds a new String whose content is the old content followed by ch, and then the variable str refers to that new String. The old content has to be copied into the new String every time. Each step therefore repeats the work of all the previous steps, so the total processing grows faster than the length of the string itself. This is why building a long string letter by letter requires a surprising amount of processing.

cpp
Notes on the code
  • str starts as an empty String, declared with the braces form
  • ch is a single character chosen for this illustration
  • Each pass through the loop creates a new String that copies everything built so far

Naming Patterns to Avoid

The guidelines name two patterns that make code harder to read: names that look similar to one another, and names written entirely in ALL_CAPS. Both are easy to write and easy to get wrong, which is why the guidelines call them out directly.

  • Common mistake

    Using names that look alike

    What it looks like
    int total_count{0};
    int total_counts{0};
    Why it fails

    A reader scanning the code can easily confuse the two names, especially when they appear close together.

    Do this instead

    Choose names that differ in meaning, such as total_count and remaining_items.

  • Common mistake

    Writing names entirely in ALL_CAPS

    What it looks like
    int MAX_ATTEMPTS{5};
    Why it fails

    The source states that ALL_CAPS names make code harder to read, so a reader has to work against the style of the code.

    Do this instead

    Give the variable a lowercase, descriptive name such as max_attempts.

  • Common mistake

    Giving a long name to a loop index

    What it looks like
    for (int loop_position_counter{0}; loop_position_counter < 10; ++loop_position_counter) { }
    Why it fails

    The long name adds noise, because the loop's purpose is already obvious and readers expect a loop index to be named i.

    Do this instead
    Use for (int i{0}; i < 10; ++i) { }
  • Common mistake

    Declaring several names in one statement

    What it looks like
    int width, height{0};
    Why it fails

    The reader must work out whether width also starts at zero, because the initializer is attached only to the last name.

    Do this instead

    Write int width{0}; and int height{0}; on separate lines.

Practicing Declarations

MEDIUM

Rewrite the following declarations so that each declaration introduces one name, uses the braces form for a named type, and gives each variable a name that matches its scope: int a, b{0}; then a loop index used only inside a for loop named loop_index_for_iterating_over_rows, and an ALL_CAPS constant named MAX_ROWS.

Hints
  • Split the shared declaration so each name has its own statement and its own initial value.
  • A loop index used only inside the loop is common and local, so a short name such as i fits.
  • Replace the ALL_CAPS name with a lowercase, descriptive name.

Putting the Rules Together

The guidelines are not separate rules to memorize in isolation. Each declaration should introduce one name. The initialization should follow the braces form for named types and the equals form for auto. The name's length should reflect how common and how widely visible the variable is. And the name should be distinct from similar-looking names and should not be written in ALL_CAPS. Applied together, these choices make a large body of code much easier to read.

Key Takeaways

  • Declare one name in each declaration so every initial value is easy to match with its variable.
  • Use the braces form for declarations with a named type and the equals form for declarations using auto.
  • Keep common and local names short, such as a loop index i, and give uncommon and nonlocal names longer, more descriptive names.
  • Avoid similar-looking names and ALL_CAPS names, since both make code harder to read.
  • Building a string with str = str + ch creates a new String that copies the old content, so long strings built this way require a lot of processing.

Related concepts

More concepts starting with D