我为什么要初始化他们在声明的顺序成员变量?(Why should I initialize memb

2019-06-27 15:50发布

我在写一些代码,今天得到了一个奇怪的编译错误,这似乎是由不同的顺序比他们被宣布初始化成员变量引起的。

例:

class Test {
    int a;
    int b;

public:
    Test() : b(1), a(2) {
    }
};

int main() {
    Test test;
    return 0;
}

然后,如果我编译它-Werror -Wall

$ g++ -Werror -Wall test.cpp
test.cpp: In constructor ‘Test::Test()’:
test.cpp:3:9: error: ‘Test::b’ will be initialized after [-Werror=reorder]
test.cpp:2:9: error:   ‘int Test::a’ [-Werror=reorder]
test.cpp:6:5: error:   when initialized here [-Werror=reorder]
cc1plus: all warnings being treated as errors

我认识到, -Wall明确要求GCC去过度的顶部有警告,但我相信有他们所有的原因。 因此,初始化成员变量的顺序怎么会事?

Answer 1:

究其原因是因为他们在他们在你的类中声明的顺序进行初始化,而不是为了你在构造函数初始化它们,它的警告你,你的构造函数的订单将不会被使用。

这是为了帮助防止出现错误,其中的初始化b依赖于a或反之亦然。

这样做的原因排序是因为只有一个析构函数,它有挑一“逆序”破坏类成员。 在这种情况下,最简单的解决方案是使用类中声明的顺序,以确保属性被以正确的顺序相反总是破坏。



Answer 2:

我为什么要初始化他们在声明的顺序成员变量?

成员在他们的声明相同的顺序进行初始化,您是否希望与否。 该警告是告诉你的顺序你所要求的从初始化执行的实际顺序不同。



Answer 3:

你不应该,因为它降低了可读性,可能引起误解。

如果你这样做:

Test() : b(1), a(b) {}

这样看来, b然后a都设定到1 ,而实际上的未初始化的值b被用来初始化ab被初始化为1



Answer 4:

实际上,编译器总是初始化中声明的顺序变量,即使你写在一个不同的顺序初始化。 因此,如果你不写初始化中声明的顺序,你的初始化的顺序不适合初始化的顺序,这可能会导致微妙的错误如果initialisations互相依赖。

例如,考虑代码

Test(): b(42), a(b) {}

这是因为一个bug a之前初始化b ,但它看起来 OK。 如果您在声明的顺序(这是初始化的顺序)写出来,错误得到明显:

Test(): a(b), b(42) {}

请注意,错误也可以比微妙的; 例如想象ab是类类型,其输出的东西在他们的构造函数; 然后用“不正确”为了你会认为b的输出应该出现前a S'时,现实中的反向不会发生。 如果a首先出现的输出会导致一个无效的文件,这也是一个错误,但也没有办法,如果构造函数是在另一种译法单元(除了一个事实,即编译器无法知道,如果重新排序是编译器可能注意到这个问题或者是不是一个错误)。 因此,它是合理的,编译器只是警告不匹配的订单大约每个实例。



Answer 5:

我认识到,-Wall明确要求GCC去过度的顶部有警告,但我相信有他们所有的原因。

-Wall仅仅是一个开始。 相反的是顾名思义,-Wall并不启用所有警告。 有一些警告,可以说是“洁癖”,但这些恰恰是-Wall不启用警告。 我总是用-Wall加上其他人。

至于您的投诉,正如其他人已经指出的那样,有一个很好的理由此警告。 仅仅因为你指定的顺序并不意味着编译器将使用该命令。 编译器必须按标准使用的顺序是基于类的定义。



文章来源: Why should I initialize member variables in the order they're declared in?