简体   繁体   English

C ++内联初始化成员变量的正确方法

[英]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. 在Microsoft Visual Studio中运行“运行代码分析”时,它会警告初始化所有变量。

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]{}; 摆脱了警告的a ,但没有data被添加,但你可以修复{}以后像这样char data[5]{}; this seems to make the code analysis happy. 这似乎使代码分析变得愉快。

That got me thinking, you can also initialize a like int a{0}; 这让我想,你也可以初始化aint a{0};

So my question is, are these all valid, and which is preferred? 所以我的问题是,这些都是有效的,哪个更受欢迎?

Side note: I noticed std::array has _Ty _Elems[_Size]; 旁注:我注意到std::array_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 还想添加这段代码:#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: gcc9.1 -std=c++17 -Wall下 - gcc9.1 -std=c++17 -Wall没有产生警告,但clang8.0 -std=c++17 -Wall下的相同代码给了我:

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? 哪一个是规格?

In C++ for each declarator, the initializer may be one of the following: 在每个声明符的C ++中,初始值设定项可能是以下之一:

1. ( expression-list )
2. = expression 
3. { initializer-list }

The description for these are as follows: 这些描述如下:

  1. comma-separated list of arbitrary expressions and braced-init-lists in parentheses 逗号分隔的任意表达式列表和括号中的braced-init-lists
  2. the equals sign followed by an expression 等号然后是表达式
  3. braced-init-list: possibly empty, comma-separated list of expressions and other braced-init-lists braced-init-list:可能为空,逗号分隔的表达式列表和其他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 . 要初始化类中的数据成员,我个人更喜欢使用braced initializer器进行类初始化,因为在这种情况下我们不必编写用户定义的default constructor编译生成的一个总是高效的

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 有关更多信息,请参阅初始化

The guideline from CPPCoreGuidelines on this states: Don't define a default constructor that only initializes data members; CPPCoreGuidelines关于此的指导原则: 不要定义仅初始化数据成员的默认构造函数; 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: 关于缺少与std::array相关的警告的另一个问题,GCC有一条说明:

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. 我相信MSVC也是如此。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM