C++ 为什么我应该按照声明的顺序初始化成员变量?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12222417/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why should I initialize member variables in the order they're declared in?
提问by Brendan Long
I was writing some code today and got a weird compile error, which seems to be caused by initializing member variables in a different order than they were declared.
我今天写了一些代码,遇到了一个奇怪的编译错误,这似乎是由于成员变量的初始化顺序与声明顺序不同造成的。
Example:
例子:
class Test {
int a;
int b;
public:
Test() : b(1), a(2) {
}
};
int main() {
Test test;
return 0;
}
Then if I compile it with -Werror -Wall
:
然后如果我编译它-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
I realize that -Wall
is explicitly asking GCC to go over-the-top with warnings, but I assume there's a reason for all of them. So, how could the order of initializing member variables matter?
我意识到这-Wall
明确要求 GCC 发出警告,但我认为所有这些都是有原因的。那么,初始化成员变量的顺序有什么关系呢?
回答by Mark B
The reason is because they're initialized in the order they're declared in your class, not the order you initialize them in the constructor and it's warning you that your constructor's order won't be used.
原因是因为它们是按照它们在您的类中声明的顺序进行初始化的,而不是您在构造函数中初始化它们的顺序,并且警告您将不会使用您的构造函数的顺序。
This is to help prevent errors where the initialization of b
depends on a
or vice-versa.
这是为了帮助防止初始化所b
依赖的错误,a
反之亦然。
The reason for this ordering is because there is only one destructor, and it has to pick a "reverse order" to destroy the class member. In this case, the simplest solution was to use the order of declaration within the class to make sure that attributes were always destroyed in the correct reverse order.
这种排序的原因是因为只有一个析构函数,它必须选择一个“相反的顺序”来销毁类成员。在这种情况下,最简单的解决方案是使用类中的声明顺序来确保属性总是以正确的相反顺序销毁。
回答by David Rodríguez - dribeas
Why should I initialize member variables in the order they're declared in?
为什么我应该按照声明的顺序初始化成员变量?
The members willbe initialized in the same order they are declared, whether you want it or not. The warning is telling you that the order you are asking for differs from the actual order of execution of initialization.
无论您是否需要,成员都将按照声明的顺序进行初始化。警告告诉您您要求的顺序与初始化的实际执行顺序不同。
回答by CB Bailey
You shouldn't because it decreases readability and is potentially misleading.
您不应该这样做,因为它会降低可读性并且可能会产生误导。
If you did:
如果你这样做:
Test() : b(1), a(b) {}
it would appear that b
then a
were both set to 1
, whereas actually the uninitialized value of b
is used to initialize a
before b
is initialized to 1
.
看起来b
thena
都设置为1
,而实际上未初始化的值b
用于在初始化为a
之前b
进行初始化1
。
回答by celtschk
Actually the compiler alwaysinitializes the variables in the order of declaration, even if you write the initializers in a different order. Therefore if you don't write the initializations in the order of declaration, the order of your initializers does not fit the order of initialization, which may lead to subtle bugs if the initialisations depend on each other.
实际上编译器总是按照声明的顺序初始化变量,即使你以不同的顺序编写初始化程序。因此,如果您不按照声明的顺序编写初始化,则您的初始化程序的顺序与初始化的顺序不符,如果初始化相互依赖,这可能会导致细微的错误。
For example, consider the code
例如,考虑代码
Test(): b(42), a(b) {}
This is a bug because a
is initialized before b
, but it looksOK. If you write it in the order of declaration (which is the order of initialization), the bug gets obvious:
这是一个错误,因为a
在 之前初始化b
,但看起来不错。如果按照声明的顺序(也就是初始化的顺序)来写,bug就很明显了:
Test(): a(b), b(42) {}
Note that the bug can also be subtler than that; for example imagine a
and b
are class types which output something in their constructor; then with the "incorrect" order you'd think that b
's output should appear before a
's when in reality the reverse will happen. If a
's output appearing first will lead to an invalid file, that's also a bug, but there's no way the compiler could notice the problem if the constructors are in another translation unit (apart from the fact that the compiler cannot know if reordering is or is not a bug). Therefore it's reasonable that the compiler just warns about every instance of non-matching order.
请注意,该错误也可能比这更微妙;例如,想象a
和b
是在其构造函数中输出某些内容的类类型;然后使用“不正确”的顺序,您会认为b
's 的输出应该出现在a
's之前,而实际上相反的情况会发生。如果a
的输出首先出现将导致无效文件,这也是一个错误,但是如果构造函数在另一个翻译单元中,编译器将无法注意到这个问题(除了编译器不知道重新排序是否是或不是错误)。因此,编译器对每个不匹配顺序的实例发出警告是合理的。
回答by David Hammen
I realize that -Wall is explicitly asking GCC to go over-the-top with warnings, but I assume there's a reason for all of them.
我意识到 -Wall 明确要求 GCC 发出警告,但我认为所有这些都是有原因的。
-Wall is just a start. Contrary to what the name implies, -Wall does not enable all warnings. There are some warnings that are arguably "over the top", but those are precisely the warnings that -Wall does not enable. I always use -Wall plus others.
-Wall 只是一个开始。与名称所暗示的相反,-Wall 不会启用所有警告。有一些警告可以说是“过度”,但这些警告恰恰是 -Wall 没有启用的警告。我总是使用 -Wall 加上其他人。
As for your complaint, as others have already noted, there is a very good reason for this warning. Just because you specify an order does not mean the compiler will use that order. The order that the compiler must use per the standard is based upon the class definition.
至于你的投诉,正如其他人已经指出的,这个警告是有充分理由的。仅仅因为您指定一个顺序并不意味着编译器将使用该顺序。编译器必须按照标准使用的顺序基于类定义。
回答by Darshan Bhat
Initializer list gives the flexibility of initializing variables in any order. However, the actual initialization happens according to the order in which you have declared the class members. To avoid this warning you have to re-order the initialization/declaration.
初始化列表提供了以任何顺序初始化变量的灵活性。但是,实际的初始化是根据您声明类成员的顺序进行的。为避免此警告,您必须重新排序初始化/声明。