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

C++ proper way to inline initialize member variables

给定示例代码:

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

当运行微软"Run code analysis"Visual Studio时,提示初始化所有变量。

现在我知道你可以通过多种方式做到这一点,创建一个默认构造函数,例如:

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

这样警告就消失了。但是,如果您不想手动创建默认构造函数怎么办。

类似于:

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

摆脱了 a 但不是 data 的警告,尽管你可以通过在后面添加 {} 来解决这个问题: char data[5]{}; 这似乎使代码分析快乐。

这让我开始思考,你也可以像 int a{0};

一样初始化 a

所以我的问题是,这些都有效吗?哪个是首选?

旁注:我注意到 std::array_Ty _Elems[_Size];,它从不在任何地方初始化,它后面也没有 {},我假设他们只是忽略了这个警告?或者他们正在做一些我没有注意到 "fix" 警告的事情?

还想补充一下这段代码: #包括 #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];
}

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};
                                                                              ^
                                                                              {}

我看到我可以将它设置为 = {}; 来修复它,只是想知道为什么一个编译器会产生警告而另一个编译器不会?哪个是规格?

指南来自CPPCoreGuidelines on this states: Don’t define a default constructor that only initializes data members; use in-class member initializers instead

所以你可以这样做:

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

关于您关于缺少与 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.

我相信 MSVC 也是如此。

在 C++ 中,对于每个声明符,初始化器可能是以下之一:

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

对这些的说明如下:

  1. comma-separated 任意表达式列表和括号中的 braced-init-lists
  2. 等号后跟表达式
  3. braced-init-list:可能为空,comma-separated 表达式列表和其他 braced-init-lists

好吧,更喜欢哪种类型的初始化实际上取决于上下文。要在 class 中初始化数据成员,我个人 更喜欢 在 class 初始化中使用 braced initializer,因为在那种情况下我们不必编写用户定义 default constructor编译器生成的总是有效的

Class members

Non-static data members can be initialized with member initializer list or with a default member initializer.

在你的情况下你可以使用:

struct S {
    char data[5] = {0}; //initialize by zero
    int a = 0;
};

或者也给它们不同的值:

struct S {
    char data[5] = {0,1,2,3,4};
    int a = 0;
};

有关详细信息,请参阅 Initialization