c++classstructinitializationmember-variables

C++ proper way to inline initialize member variables


Given the example code:

struct S {
    char data[5];
    int a;
};

When running the "Run code analysis" in Microsoft Visual Studio, It warns to initialize all variables.

Now I know you can do this a number of ways, create a default constructor such as:

S() :
    data{0},
    a{0} {
}

That makes the warning go away. But what if you don't want to manually create the default constructor.

something like:

struct S {
    char data[5];
    int a = 0;
};

gets rid of the warning for a but not data, though you can fix that by adding {} after like so: char data[5]{}; this seems to make the code analysis happy.

That got me thinking, you can also initialize a like int a{0};

So my question is, are these all valid, and which is preferred?

Side note: I noticed std::array has _Ty _Elems[_Size]; which it never initializes anywhere, nor does it have {} after it, I'm assuming they just ignore this warning? Or are they doing something I'm not noticing to "fix" the warning?

Also wanted to add that this code: #include #include

template<class T, std::size_t N>
struct static_vector {
    typename std::aligned_storage<sizeof(T), alignof(T)>::type data[N] = {0};

    T& operator[](std::size_t pos)  {
        return *std::launder(reinterpret_cast<T*>(&data[pos]));
    }
};

int main(int argc, char**) {
    static_vector<int, 10> s;
    s[0] = argc;
    return s[0];
}

under gcc9.1 -std=c++17 -Wall produces no warnings, yet the same code under clang8.0 -std=c++17 -Wall gives me:

warning: suggest braces around initialization of subobject [-Wmissing-braces]
        typename std::aligned_storage<sizeof(T), alignof(T)>::type data[N] = {0};
                                                                              ^
                                                                              {}

I see that I can set it to = {}; which fixes it, just wondering why one compiler would produce a warning when the other doesn't? Which one is to spec?


Solution

  • The guideline from CPPCoreGuidelines on this states: Don’t define a default constructor that only initializes data members; use in-class member initializers instead

    So you can just do:

    struct S {
        char data[5] = {0};
        int a = 0;
    };
    

    As to your other question about the lack of warning related to std::array, GCC has a note which states:

    Warnings from system headers are normally suppressed, on the assumption that they usually do not indicate real problems and would only make the compiler output harder to read.

    I believe this would be true of MSVC as well.