为什么初始化程序列表顺序必须匹配成员声明顺序

时间:2022-09-28 11:34:51

Why does gcc throw a hissy fit if the initializer list order doesn't match variable order in the class?

如果初始化列表顺序与类中的变量顺序不匹配,为什么gcc会抛出一个合适的东西呢?

class myClass
{
public:
   int A;
   int B;
   myClass();
};

myClass::myClass() :
B(1),
A(2)
{}

will result in:

将导致:

file.h:274: warning: 'myClass::A' will be initialized after
file.h:273: warning:   'int myClass::B
file.cpp:581: warning:   when initialized here

Is there any specific reason why this kind of warning is issued? Are there any risks associated with initializing variables of a class in order different than they are defined within the class?

发出这种警告有什么具体原因吗?是否存在与初始化类的变量相关的风险,其顺序与在类中定义的顺序不同?

(note, there is a question which touches the subject, but the answers are pretty much "because it should be so" without giving any rationale as to why it should be ordered, or what's wrong with this being out of order - I'd like to know why such a restriction exists - could someone give an example where it may backfire maybe?)

(注意,有一个问题涉及到这个主题,但答案几乎是“因为它应该是这样”而没有给出任何理由,为什么应该订购,或者这个故障有什么不对 - 我会想知道为什么存在这样的限制 - 有人会举例说明它可能适得其反吗?)

3 个解决方案

#1


13  

The warning is trying to prevent situations where you might be relying on the wrong ordering of the data members. Say you think B is initialized before A, and then you do something like this:

该警告试图防止您可能依赖于数据成员的错误排序的情况。假设您认为B在A之前初始化,然后您执行以下操作:

myClass::myClass() :
B(42), A(B) {}

Here, you have undefined behaviour because you are reading from an uninitialized B.

在这里,你有未定义的行为,因为你正在读取未初始化的B.

#2


16  

The warning is indicating that regardless of the order you use in the constructor initialization list the standard requires that non-static data members be initialized in the order they were declared. We can see this by going to the draft C++ standard section 12.6.2 Initializing bases and members paragraph 10 which says:

警告表明,无论您在构造函数初始化列表中使用的顺序如何,标准都要求按照声明的顺序初始化非静态数据成员。我们可以通过参考草案C ++标准部分12.6.2初始化基础和成员第10段来看到这一点:

In a non-delegating constructor, initialization proceeds in the following order:

在非委托构造函数中,初始化按以下顺序进行:

and includes:

Then, non-static data members are initialized in the order they were declared in the class definition (again regardless of the order of the mem-initializers).

然后,非静态数据成员按照它们在类定义中声明的顺序进行初始化(同样不管mem-initializers的顺序如何)。

Why does the standard require this? We can find a rationale for this in paper The Evolution of C++: 1985 to 1989 by Bjarne Stroustrup in section 6 it says:

为什么标准需要这个?我们可以在文章“C ++的演变:1985年到1989年”中找到一个理由,Bjarne Stroustrup在第6节中说:

The initialization takes place in the order of declaration in the class with base classes initialized before members,

初始化按类中的声明顺序进行,其中基类在成员之前初始化,

[...]

The reason for ignoring the order of initializers is to preserve the usual FIFO ordering of constructor and destructor calls. Allowing two constructors to use different orders of initialization of bases and members would constrain implementations to use more dynamic and more expensive strategies

忽略初始化器顺序的原因是保留构造函数和析构函数调用的通常FIFO顺序。允许两个构造函数使用不同的基础和成员初始化顺序将限制实现使用更动态和更昂贵的策略

#3


3  

The order of the initializer list does NOT matter. The declaration of your members in the class header defines the initialization order.

初始化列表的顺序无关紧要。类头中的成员声明定义了初始化顺序。

This is by design and required as you could have multiple ctors having totally different init list orders.

这是设计和要求,因为您可能有多个ctors具有完全不同的初始列表顺序。

So your members will ALWAYS be initialized in the order of declaration.

因此,您的成员将始终按照声明的顺序进行初始化。

#1


13  

The warning is trying to prevent situations where you might be relying on the wrong ordering of the data members. Say you think B is initialized before A, and then you do something like this:

该警告试图防止您可能依赖于数据成员的错误排序的情况。假设您认为B在A之前初始化,然后您执行以下操作:

myClass::myClass() :
B(42), A(B) {}

Here, you have undefined behaviour because you are reading from an uninitialized B.

在这里,你有未定义的行为,因为你正在读取未初始化的B.

#2


16  

The warning is indicating that regardless of the order you use in the constructor initialization list the standard requires that non-static data members be initialized in the order they were declared. We can see this by going to the draft C++ standard section 12.6.2 Initializing bases and members paragraph 10 which says:

警告表明,无论您在构造函数初始化列表中使用的顺序如何,标准都要求按照声明的顺序初始化非静态数据成员。我们可以通过参考草案C ++标准部分12.6.2初始化基础和成员第10段来看到这一点:

In a non-delegating constructor, initialization proceeds in the following order:

在非委托构造函数中,初始化按以下顺序进行:

and includes:

Then, non-static data members are initialized in the order they were declared in the class definition (again regardless of the order of the mem-initializers).

然后,非静态数据成员按照它们在类定义中声明的顺序进行初始化(同样不管mem-initializers的顺序如何)。

Why does the standard require this? We can find a rationale for this in paper The Evolution of C++: 1985 to 1989 by Bjarne Stroustrup in section 6 it says:

为什么标准需要这个?我们可以在文章“C ++的演变:1985年到1989年”中找到一个理由,Bjarne Stroustrup在第6节中说:

The initialization takes place in the order of declaration in the class with base classes initialized before members,

初始化按类中的声明顺序进行,其中基类在成员之前初始化,

[...]

The reason for ignoring the order of initializers is to preserve the usual FIFO ordering of constructor and destructor calls. Allowing two constructors to use different orders of initialization of bases and members would constrain implementations to use more dynamic and more expensive strategies

忽略初始化器顺序的原因是保留构造函数和析构函数调用的通常FIFO顺序。允许两个构造函数使用不同的基础和成员初始化顺序将限制实现使用更动态和更昂贵的策略

#3


3  

The order of the initializer list does NOT matter. The declaration of your members in the class header defines the initialization order.

初始化列表的顺序无关紧要。类头中的成员声明定义了初始化顺序。

This is by design and required as you could have multiple ctors having totally different init list orders.

这是设计和要求,因为您可能有多个ctors具有完全不同的初始列表顺序。

So your members will ALWAYS be initialized in the order of declaration.

因此,您的成员将始终按照声明的顺序进行初始化。