使用成员初始化列表初始化时如何修复 [-Wreorder] 和 [-Wuninitialized] 冲突?

问题描述

一个看起来像这样的类中:

MyClass.h

class MyClass{

public:
    MyClass();
    int x1;
    int x2;
    int x3;
    int x4;
    int x5;

private:
    int y1;
    int y2;
};

MyClass.cpp

#include "MyClass.h"

int someFunc1(int x1,int x2){
    return x1+x2;
}

int someFunc2(int x1,int x2){
    return x1+x2;
}

MyClass::MyClass(): 
    x1(1),x2(2),x3(3),x4(4),y1(someFunc1(x1,x2)),y2(someFunc2(x3,x4)),x5(y1+y2){}

main.cpp

#include "MyClass.h"

int main(int argc,char **argv)
{

    MyClass myclass;

    return 0;
}

编译器的输出

In file included from MyClass.cpp:1:
MyClass.h: In constructor ‘MyClass::MyClass()’:
MyClass.h:13:9: warning: ‘MyClass::y2’ will be initialized after [-Wreorder]
     int y2;
         ^~
MyClass.h:9:9: warning:   ‘int MyClass::x5’ [-Wreorder]
     int x5;
         ^~
MyClass.cpp:11:1: warning:   when initialized here [-Wreorder]
 MyClass::MyClass():
 ^~~~~~~
MyClass.cpp: In constructor ‘MyClass::MyClass()’:
MyClass.cpp:13:54: warning: ‘*<unkNown>.MyClass::y1’ is used uninitialized in this function [-Wuninitialized]
     y1(someFunc1(x1,x5(y1+y2){}
                                                      ^~
MyClass.cpp:13:57: warning: ‘*<unkNown>.MyClass::y2’ is used uninitialized in this function [-Wuninitialized]
     y1(someFunc1(x1,x5(y1+y2){}
                                                         ^~

我无法控制 someFunc1someFunc2,我只是以这种方式定义它们来编译代码

我可以通过删除成员初始化列表来修复这些警告,并像这样初始化构造函数主体中的数据成员:

MyClass::MyClass(){
    x1 = 1;
    x2 = 2;
    x3 = 3;
    x4 = 4;
    y1=someFunc1(x1,x2); 
    y2=someFunc2(x3,x4);
    x5=y1+y2;
}

或者我可以像这样重新排序类体中数据成员的声明:

class MyClass{
public:
    MyClass();
    int x1;
    int x2;
    int x3;
    int x4;
private:
    int y1;
    int y2;
public:
    int x5;
};

在这里我不必要地两次声明公共成员的范围!

如何修复(而不是摆脱)这些警告并仍然使用成员初始化列表进行初始化?

如您所见,第一个原始形式中的数据成员根据其用法按正确的顺序定义,但编译器本身仍然无法弄清楚。

解决方法

如您所见,第一个原始表单中的数据成员根据其用法按正确顺序定义,

相反,我们可以看到相反的情况:在第一个示例中,成员根据其用法以错误的顺序声明:

    int x5;

private:
    int y1;
    int y2;

如您所见,x5 是在 y1y2 之前声明的。因此 x5 在其他两个之前初始化。

y1(someFunc1(x1,x2)),y2(someFunc2(x3,x4)),x5(y1+y2)

在这里,您以与成员初始化不同的顺序对成员初始化列表进行了误导性排序。 -Wreorder 警告是此选择的结果。

此外,初始化器使用尚未初始化的 y1y2 值。 -Wuninitialized 警告是其后果。


但在这里我不必要地两次声明公共成员的范围!

这几乎不是问题。

如何修复(而不是摆脱)这些警告并仍然使用成员初始化列表进行初始化?

您已经展示了两种解决方案,其中一种满足您使用成员初始值设定项列表的愿望。我推荐满足您所有期望要求的解决方案。

如果你不想改变成员的顺序,那么第一个解决方案可以调整为仍然对所有其他成员使用成员初始化列表,除了依赖于后一个成员的成员:

MyClass::MyClass(): 
    x1(1),x2(2),x3(3),x4(4),x5{}
    y1(someFunc1(x1,x4))
{
    x5 = y1 + y2;
}

像这样复杂的初始化是构造函数体存在的目的。

,

您可以使用委托构造函数:

class MyClass{

public:
    MyClass() : MyClass(1,2,3,4) {}

//private:

    MyClass(int x1,int x2,int x3,int x4) :
        MyClass(x1,x2,x3,x4,someFunc1(x1,x2),someFunc2(x3,x4))
    {}

    MyClass(int x1,int x4,int y1,int y2) :
        x1(x1),x2(x2),x3(x3),x4(x4),x5(y1 + y2),y1(y1),y2(y2)
    {}
public:
    int x1;
    int x2;
    int x3;
    int x4;
    int x5;

private:
    int y1;
    int y2;
};