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

时间:2019-05-23 08:45:36

标签: c++ class struct initialization member-variables

给出示例代码:

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

在Microsoft Visual Studio中运行“运行代码分析”时,它会警告初始化所有变量。

现在我知道您可以通过多种方法来执行此操作,创建默认的构造函数,例如:

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

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

类似:

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

摆脱了a的警告,但没有摆脱data的警告,尽管您可以通过以下方式添加{}来解决此问题:char data[5]{};似乎可以进行代码分析快乐。

这让我开始思考,您也可以像a一样初始化int a{0};

所以我的问题是,这些都有效吗?哪个更可取?

旁注:我注意到std::array_Ty _Elems[_Size];,它永远不会在任何地方初始化,也没有{}之后的东西,我假设他们只是忽略了这个警告?还是他们在做我不注意“修复”警告的事情?

还想添加以下代码:     #包括     #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};
                                                                              ^
                                                                              {}

我看到可以将其设置为= {};来对其进行修复,只是想知道为什么一个编译器会在另一个不生成警告时发出警告?要指定哪一个?

2 个答案:

答案 0 :(得分:3)

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

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

这些的描述如下:

  1. 用逗号分隔的任意表达式列表和括号中的括号初始列表
  2. 等号后跟表达式
  3. braced-init-list:可能是空的,用逗号分隔的表达式列表和其他braced-init-list

究竟哪种类型的初始化实际上取决于上下文。要在类中初始化数据成员,我个人会使用braced initializer在类初始化中首选,因为在这种情况下,我们不必编写用户定义的default constructor

  

班级成员

     

可以使用member initializer listdefault 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

答案 1 :(得分:1)

CPPCoreGuidelines对此的指导原则是: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)有一条说明:

  

通常会抑制系统标头中的警告,因为它们通常不会指示实际问题,只会使编译器的输出难以阅读。

我相信MSVC也是如此。