Search code examples
c++undefined-behaviorvariable-initialization

Is there a reason to use zero-initialization instead of simply not defining a variable when it is going to be updated before the value is used anyway?


I came across a code example learncpp.com where they zero-initialized a variable, then defined it with std::cin:

#include <iostream>  // for std::cout and std::cin

int main()
{
    std::cout << "Enter a number: "; // ask user for a number

    int x{ }; // define variable x to hold user input (and zero-initialize it)
    std::cin >> x; // get number from keyboard and store it in variable x

    std::cout << "You entered " << x << '\n';
    return 0;
}

Is there any reason that on line 7 you wouldn't just not initialize x? It seems zero-initializing the variable is a waste of time because it's assigned a new value on the next line.


Solution

  • Is there any reason that on line 7 you wouldn't just not initialize x?

    In general, it is advised that local/block scope built in types should always be initialized. This is to prevent potential uses of uninitialized built in types which have indeterminate value and will lead to undefined behavior.

    In your particular example though since in the immediate next line we have std::cin >> x; so it is safe to omit the zero initialization in the previous line.

    Note also that in your example if reading input failed for some reason then prior to C++11, x still has indeterminate value but from C++11(&onwards) x will no longer has indeterminate value according to the below quoted statement.

    From basic_istream's documentation:

    If extraction fails (e.g. if a letter was entered where a digit is expected), zero is written to value and failbit is set. For signed integers, if extraction results in the value too large or too small to fit in value, std::numeric_limits<T>::max() or std::numeric_limits<T>::min() (respectively) is written and failbit flag is set. For unsigned integers, if extraction results in the value too large or too small to fit in value, std::numeric_limits<T>::max() is written and failbit flag is set.

    It seems zero-initializing the variable is a waste of time because it's redefined on the next line.

    As i said, in your example and assuming you're using C++11(& higher), you can safely leave off the zero-initialization.


    then defined it with std::cin

    No the use of std::cin does not "define" it(x). Definition happened only once when you wrote:

    int x{ }; //this is a definition
    

    Even if you leave the zero initialization, then also it will be a definition:

    int x;  //this is also a definition but x is uninitialized here