如果初始化程序列表顺序与类中的变量顺序不匹配,为什么gcc会抛出异议?
class myClass
{
public:
int A;
int B;
myClass();
};
myClass::myClass() :
B(1),
A(2)
{}
将导致:
file.h:274: warning: 'myClass::A' will be initialized after
file.h:273: warning: 'int myClass::B
file.cpp:581: warning: when initialized here
是否有任何具体原因可以发出此类警告?初始化类的变量是否存在与类中定义的顺序不同的风险?
(请注意,有a question触及主题,但答案非常多,因为它应该如此"没有给出为什么的任何理由它应该被命令,或者这个故障有什么不对 - 我想知道为什么存在这样的限制 - 有人可以给出一个可能适得其反的例子吗?)
答案 0 :(得分:18)
警告表明,无论您在构造函数初始化列表中使用的顺序如何,该标准都要求按照声明的顺序初始化非静态数据成员。我们可以通过转到draft C++ standard部分12.6.2
初始化基础和成员段 10 来看到这一点,其中包含:
在非委托构造函数中,初始化继续进行 以下顺序:
并包括:
然后,按照它们的顺序初始化非静态数据成员 在类定义中声明(再次无论顺序如何 MEM-初始化)。
为什么标准需要这个?我们可以在文章The Evolution of C++: 1985 to 1989中找到Bjarne Stroustrup在6
部分中提到的理由:
初始化按照声明的顺序进行 在成员之前初始化基类的类,
[...]
忽略初始化器顺序的原因是为了保留初始化器 通常的构造函数和析构函数调用的FIFO排序。允许两个 构造函数使用不同的基数和初始化顺序 成员会限制实现使用更多动态和更多 昂贵的策略
答案 1 :(得分:14)
警告试图阻止您可能依赖于数据成员的错误排序的情况。假设您认为B在A之前初始化,然后您执行以下操作:
myClass::myClass() :
B(42), A(B) {}
在这里,您有未定义的行为,因为您正在阅读未初始化的B
。
答案 2 :(得分:3)
初始化列表的顺序 NOT 很重要。 类头中的成员声明定义了初始化顺序。
这是设计和要求,因为您可能有多个ctors具有完全不同的初始列表顺序。
因此,您的成员将始终按声明的顺序初始化。
答案 3 :(得分:-3)
我认为这只是清洁问题。类成员的声明顺序在类的头文件中定义,而构造函数在.cpp
文件中定义。
假设您要为该类添加另一个构造函数,并且仅查看具有.cpp
的B(1), A(2)
文件,您可能会错误地认为B
将被初始化在 A
之前,因此写错了一些东西(例如,B(42), A(B)
)。警告是从一开始就防止这种情况发生。