Variables and Fundamental Types

Declaring and Initializing Variables

Before using any variable, two things must happen: it is declared (so that the compiler knows the variable’s name and type), and it is initialized (so that the variable’s initial value is well defined). This is one of the oldest sources of bugs in the language, to confuse these two requirements or forget the second one.

#include <iostream>

int main()
{
    int x;
    std::cout << x << '\n';
}

A variable may have its name and type declared, but if no value is provided, it is uninitialized. Any reading of an automatic variable that has not been initialized is undefined behavior.

It may give the appearance of being zero, it may give the appearance of being a "garbage" value remaining from previous use of the variable's memory, and it can result in anything other than reliable code depending on what compiler, what optimization level, and what value, if any, previously occupied that location in memory.

By some rules in the language, an automatic variable can technically have its declaration not come with an initialization value, but reliable program text will avoid reading such a value and it is something I still continue to see way too often in code reviews.

The compiler is not warning you, but the error exists.

C++ provides several initialization forms that give a variable its first value. The ones you are most likely to see used are copy initialization, direct initialization, brace initialization, and value initialization.

int a = 10;
// Declare b before code needs to call it
int b(20);
int c{30};
int d{};

There are two benefits that brace initialization affords you: it will not allow for any narrowing conversions, and it is the same across fundamental types, aggregates, standard containers, and almost any user defined types. This removes some of the knowledge of special cases that you do need to acquire.

int e = 3.14;
int f{3.14};

In some cases, initializing with a floating point value can result in truncation of the fractional part if some forms of initialization are used, as narrowing conversions are allowed: brace initialization prevents these conversions from happening at compile time. This type of error is always caught much earlier in the compiler than any truncated value will be discovered during testing.

A simple case where value initialization using empty braces offers an added benefit is initialization to zero with less typing than was previously afforded by the zero literal. Class types that have a default constructor will call the default constructor using a uniform mechanism.

#include <iostream>
#include <string>

int main()
{
    int count{0};
    std::string name{"Alice"};
    double temperature{36.6};

    std::cout << name << " counted to "
              << count << " at "
              << temperature << " degrees\n";
}

Before the variable is ever used, it should always have been assigned a type, a name, and a definite value; this will make certain that an indefinite value does not find its way into the rest of the program. This use of brace initializers in addition helps to see initialization and eliminates narrowing conversions more readily.

Exercise: Declaring and Initializing VariablesStarter code, hints and solutionOpenClose
Guided practiceBeginner · 10–15 min

Practice: Declaring and Initializing Variables

Work through the mission, reveal hints only when needed, and compare your result with the model solution.

Your challenge

Initialize count to 3 rather than 0 without changing the other variables. Predict the sentence and identify the variable responsible for its change.

Mission checklist

  1. Run the starter as a baseline, then predict the change requested in Your challenge.
  2. Make that change in your editor; use the lesson-specific hints if you need help.
  3. Compile and run your answer, then compare with the worked solution and explain the result.

Starter program

This is the working baseline, not the completed answer. Compile as C++20, then make the change described above.

#include <iostream>
#include <string>

int main()
{
    int count{0};
    std::string name{"Alice"};
    double temperature{36.6};

    std::cout << name << " counted to "
              << count << " at "
              << temperature << " degrees\n";
}

Hints

Hint 1

Match the brace initializer to each type: count is an int, name is a std::string, and temperature is a double. These values exist before the output statement runs.

Hint 2

Change count inside its declaration, then locate << count in the output chain. Use an integer initializer there; the other two variables need not change.

Worked solution

count is initialized to 3 instead of 0. name and temperature are unchanged, so only the count embedded in the sentence changes.

#include <iostream>
#include <string>

int main()
{
    int count{3};
    std::string name{"Alice"};
    double temperature{36.6};

    std::cout << name << " counted to "
              << count << " at "
              << temperature << " degrees\n";
}

Example output

Alice counted to 3 at 36.6 degrees

0 comments

No comments yet. Be the first.

Add a comment

About CppLearn

CppLearn is an interactive, free reference for modern C++. In each lesson, you'll find out how the language works, rather than just lines of code that you can copy and paste. We cover concepts starting from beginner lessons on fundamentals and proceed to templates, move semantics, smart pointers, and areas that usually trap or scare C++ learners.