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

时间:2014-06-18 12:04:23

标签: c++ constructor initializer-list

如果初始化程序列表顺序与类中的变量顺序不匹配,为什么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触及主题,但答案非常多,因为它应该如此"没有给出为什么的任何理由它应该被命令,或者这个故障有什么不对 - 我想知道为什么存在这样的限制 - 有人可以给出一个可能适得其反的例子吗?)

4 个答案:

答案 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文件中定义。

假设您要为该类添加另一个构造函数,并且仅查看具有.cppB(1), A(2) 文件,您可能会错误地认为B 将被初始化在 A 之前,因此写错了一些东西(例如,B(42), A(B))。警告是从一开始就防止这种情况发生。