成员初始化者的顺序

时间:2017-08-23 09:27:48

标签: c++ class member-initialization

以下代码提供正确的输出,如果我声明变量... imports: [ RouterModule, RouterModule.forRoot([ { path: '', redirectTo: 'client', pathMatch: 'full' }, { path: 'home', component: HomeComponent }, { path: 'client', component: ViewClientsComponent }, { path: 'dashboard', component: DashboardComponent }, { path: 'reports', component: ReportsComponent }, { path: '**', redirectTo: 'client' } ]) ] ... i,请j

int i, j;

但是如果我声明变量class A { int i, j; public: A(int val) : i(val), j(i + 1) { cout<<i<<endl<<j<<endl; } }; i,就像j一样。然后int j, i;打印垃圾值

j

那么,是否取决于变量声明的顺序?

3 个答案:

答案 0 :(得分:2)

  

是否取决于变量声明的顺序?

是的,数据成员总是按其声明的顺序初始化,这与成员初始化列表的顺序无关。

这意味着,对于您的第二个代码段,j始终在i之前初始化;但是,当成员初始化程序i初始化时,它仍未初始化。

对象的完整initialization order为:

(强调我的)

  

列表中成员初始值设定项的顺序是无关紧要的:实际的   初始化顺序如下:

     

1)如果构造函数是针对派生程度最高的类的虚拟基础   类按它们出现的顺序初始化   基类深度优先从左到右遍历基类声明   (从左到右指的是基本说明符列表中的外观)

     

2)然后,直接基类按从左到右的顺序初始化为   它们出现在这个类的基本说明符列表中

     

3)然后,非静态数据成员按顺序初始化   类定义中的声明

     

4)最后,执行构造函数的主体

答案 1 :(得分:2)

  

是否取决于变量声明的顺序?

绝对!初始化程序出现在初始化列表中的顺序将被标准忽略;只有声明的顺序。这样做是为了使初始化的反向顺序为&#34;在析构函数中有意义,即使可能存在多个构造函数,初始化程序列表按不同顺序排列。

以下是C ++标准(12.6.2.10)的相关部分:

  

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

     
      
  • 首先,仅对于派生程度最高的类(1.8)的构造函数,虚拟基类按照它们出现在基类的有向无环图的深度优先从左到右遍历的顺序进行初始化,其中“从左到右”是派生类base-specifier-list中基类出现的顺序。
  •   
  • 然后,直接基类按声明顺序初始化,因为它们出现在base-specifier-list中(无论mem-initializers的顺序如何)。
  •   
  • 然后,非静态数据成员按照它们在类定义中声明的顺序进行初始化(同样不管mem-initializers的顺序如何)。
  •   
  • 最后,执行构造函数体的复合语句。
  •   
     

[注意:声明顺序的目的是确保以初始化的相反顺序销毁基础和成员子对象。 - 结束说明]

答案 2 :(得分:1)

  

是否取决于变量声明的顺序?

是的,数据成员的顺序(即:i中的jA} 已初始化 ,对应于声明的顺序,而不是它们出现在构造函数的成员初始化列表中的顺序。

A

中构造函数的成员初始值设定项列表
A(int val) : i(val), j(i + 1)

没有说明这些数据成员初始化的顺序。

如果在j之前宣布i(即:j),数据成员i仍将在int j, i之前初始化。在这种情况下,j正在初始化为i + 1,但此时i未初始化,这可能会导致j包含垃圾。

在GCC中,您可以通过提供-Wreorder选项在这些情况下显示警告,该选项已通过传递-Wall选项启用。