问题
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?
回答1:
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.
回答2:
In C++ for each declarator, the initializer may be one of the following:
1. ( expression-list )
2. = expression
3. { initializer-list }
The description for these are as follows:
- comma-separated list of arbitrary expressions and braced-init-lists in parentheses
- the equals sign followed by an expression
- braced-init-list: possibly empty, comma-separated list of expressions and other braced-init-lists
Well which type of initialization to prefer actually depends upon context. To initialize data members in a class I personally prefer in class initialization using braced initializer
, as in that case we don't have to write a user defined default constructor
, compiler generated one is always efficient.
Class members
Non-static data members can be initialized with member initializer list or with a default member initializer.
In your case you can probably use:
struct S {
char data[5] = {0}; //initialize by zero
int a = 0;
};
or to give them different values also:
struct S {
char data[5] = {0,1,2,3,4};
int a = 0;
};
For more info see Initialization
来源:https://stackoverflow.com/questions/56271358/c-proper-way-to-inline-initialize-member-variables