Skip to content
Theory · Variables and Types · lesson 2 of 9

Initialization: =, () and {}

The value a variable gets in its declaration is its initial value, and this step is called initialization. It is what goes into the box at the moment the name sticker goes on. If the value does not suit the variable's type, the compiler converts it on its own, possibly losing part of it:

C++
#include <iostream>

int main() {
    double price = 2.9;
    int whole = price;
    std::cout << whole << '\n';  // 2
}

An int holds only whole numbers, so the fraction 0.9 is dropped, with no rounding. It is like a box for whole tiles: the piece 0.9 is broken off the tile 2.9, and 2 goes into the box. The compiler reports neither an error nor a warning, and the program prints 2.

Three forms

An initial value can be written in three ways:

C++
int a = 5;
int b(5);
int c{5};
std::cout << a << ' ' << b << ' ' << c << '\n';  // 5 5 5
  • int a = 5; is the form with the = sign, familiar and the most common;
  • int b(5); is the form with parentheses;
  • int c{5}; is the form with braces.

For an int and 5, all three lines do the same thing. They differ in how they treat a value that does not fit: = and parentheses convert it, as in the example above.

Empty braces set the value to zero: int total{}; means the same as int total{0};. The next example shows what makes braces better than the other two forms.

Braces against narrowing

A conversion that may lose part of a value is called a narrowing conversion. It happens in two cases:

  • a fractional number goes into an integer type;
  • a number does not fit in the new type.

What matters is not the type's size in bytes but whether part of the value can be lost. Braces forbid narrowing:

C++
int count{2.5};  // ✗
TEXT
error: type 'double' cannot be narrowed to 'int' in initializer list [-Wc++11-narrowing]

This is a compile error: the program does not build until the value is fixed.

Braces let through an integer constant that fits the new type exactly: double ratio{2}; compiles. A floating value never goes into an integer type through braces, not even 2.0: int n{2.0}; does not compile either. So int whole{price}; from the first example is narrowing too.

That makes braces the strictest of the three forms: they catch a type mistake at once. Interviewers like to ask this: how does int x{2.5}; differ from int x = 2.5;?

Type from the initial value

auto can stand in place of a type, and then the compiler deduces the type from the initial value, as if it stamped the box by what was put inside. The type matches the literal's type:

  • auto count = 10; gives an int;
  • auto price = 2.5; gives a double;
  • auto ratio = 2.5f; gives a float.

The type comes from the initial value, so auto does not work without one: auto total; does not compile.

With auto, you can get the wrong type without noticing. If a fractional sum starts as auto total = 0;, the literal 0 gives an int. Then the assignment total = total + 2.5; keeps only 2 in total, and the compiler stays silent. You need a literal of the right type: auto total = 0.0;.

Common mistake

A variable is declared without an initial value and then read:

C++
int total;
total = total + 5;  // ✗
TEXT
warning: variable 'total' is uninitialized when used here [-Wuninitialized]

If a variable inside a function is declared without an initial value, its value is indeterminate. This is the box that holds an unpredictable value. Reading such a value is undefined behavior: the C++ standard does not say what the program will do. The compiler only warns, so give the value right away: int total{0}; or int total{};.

Key points

  • Initialization sets the initial value; = and parentheses silently convert a value that does not fit, and the fraction is lost.
  • Braces forbid narrowing: int n{2.0}; and int whole{price}; do not compile, while double ratio{2}; does.
  • auto takes the type from the initial value: auto total = 0; is an int.
  • A variable without an initial value must not be read, so give it a value right away, for example int total{};.

Subscribe to take the course

The course is free. Sign in with Telegram and subscribe to the channel to open every lesson.

Sign in another way