Why std::array<int, 10> x is not zero-initialized but std::array<int, 10> x = std::array<int, 10>() seems to be?

16,889

Using {} or () as an initializer, with our without =, results in value initialization. For a type with an implicitly-declared constructor, value initialization implements zero initialization, which as its name suggests sets each primitive element to 0. This occurs before the constructor may be run, but in this case, the constructor does nothing.

Because the constructor does nothing (it is trivial), it is possible to see uninitialized data.

As for C-style arrays, the behavior is similar if you use = {} instead of = T(), as the latter is illegal. T() would ask for a temporary array object to be assigned to the named object, but arrays can't be assigned. = {} on the other hand assigns a braced-initializer-list to the array, and a braced-initializer-list is a special syntactic construct which is neither an expression nor an object.

Share:
16,889
Vincent
Author by

Vincent

Researcher, astrophysicist, computer scientist, programming language expert, software architect and C++ standardization committee member. LinkedIn: https://www.linkedin.com/in/vincent-reverdy

Updated on June 05, 2022

Comments

  • Vincent
    Vincent almost 2 years

    I have just asked two questions about array and value initialization here and here. But with this code, I'm lost:

    #include <iostream>
    #include <iomanip>
    #include <array>
    
    template <class T, class U = decltype(std::declval<T>().at(0))>
    inline U f1(const unsigned int i)
    {T x; return x.at(i);}
    
    template <class T, class U = decltype(std::declval<T>().at(0))>
    inline U f2(const unsigned int i)
    {T x = T(); return x.at(i);}
    
    int main()
    {
        static const unsigned int n = 10;
        static const unsigned int w = 20;
        for (unsigned int i = 0; i < n; ++i) {
            std::cout<<std::setw(w)<<i;
            std::cout<<std::setw(w)<<f1<std::array<int, n>>(i);
            std::cout<<std::setw(w)<<f2<std::array<int, n>>(i);
            std::cout<<std::setw(w)<<std::endl;
        }
        return 0;
    }
    

    As expected, f1 return arbitrary values as its values are not zero-initialized. But f2 seems to return exclusively zero values:

                       0                   0                   0
                       1                  61                   0
                       2                   0                   0
                       3                   0                   0
                       4           297887440                   0
                       5               32767                   0
                       6             4196848                   0
                       7                   0                   0
                       8           297887664                   0
                       9               32767                   0
    

    Personally I thought that f2 will create an array with arbitrary values and copy/move it to x. But it does not seem to be the case.

    So, I have two questions:

    • Why?
    • Do C++11 std::array<T, N> and C-style T[N] have the same behaviour in such a situation?