c ++中初始化程序和默认初始化程序列表之间的区别

kar*_*hik 8 c++ constructor

嗨,我有一个问题,但很长一段时间都找不到答案,也就是说,下面两条关于参数初始化的陈述有什么区别?

class A::A() 
    : a(0), b(0), c(0) 
{ 
}

class A::A() 
{ 
    a = 0 
    b = 0; 
    c = 0; 
} 
Run Code Online (Sandbox Code Playgroud)

我知道有"直接初始化"和"复制初始化",但我不知道其他差异是什么,以及是否有关于第一个语句的描述?

提前致谢

Pét*_*rök 25

使用初始化列表,只使用给定值创建和初始化成员一次.

使用赋值,使用默认值初始化成员,然后在构造函数体中重新分配.

在某些情况下(常量,引用),您只能使用初始化列表,因为

  • 这些必须用有效值初始化,并且
  • 一旦建成,重新分配它们是非法的.

在其他情况下,即使可以进行赋值,初始化列表仍然是可取的,因为它避免了额外的工作(双重初始化,对于某些类型来说可能代价很高)并且遵循一个常见的习惯用法,使您的代码更易于理解和维护.

需要注意的一点是,成员初始化的顺序是由它们的声明顺序定义的,而不是它们在初始化列表中列出的顺序.例如

class Example {
  int a, b, c;

  Example() : a(1), c(2), b(c) {}
}
Run Code Online (Sandbox Code Playgroud)

产生未定义的行为,因为之前b已初始化,因此具有未定义的值.为了避免混淆以及可能存在这些微妙的错误,请始终按照在类中声明的顺序列出初始化列表中的成员. c

这一开始可能看起来很模糊,但有理由这样做.在C++中,保证类的所有成员都以与创建它们的顺序完全相反的方式被销毁.现在,类可以有多个构造函数,每个构造函数都有自己的初始化列表,并且(不幸的是,有人可能会说)初始化列表可以按程序员想要的任何方式进行排序.如果初始化列表的顺序确定了初始化的实际顺序,则运行时应以某种方式维护有关每个对象的数据,以便记住它所创建的构造函数,以及应该以何种顺序销毁其成员.这将导致运行时开销,没有明显的好处,因此 - 符合一般C++哲学"仅为您使用的内容付费" - 决定初始化顺序由声明顺序一劳永逸地定义.

  • 当初始化很昂贵,或者处理不是默认构造的类型时,这变得至关重要. (3认同)

kar*_*hik 5

默认初始化列表的目的是在类中初始化常量变量.因为常量变量在初始化对象之前初始化.

我提供了一个示例来解释这两个初始化之间的区别:

 class A
   {
       private:
          const int x;

  };

  A::A():x(5)        //this code works fine
  {

    }

    A::A()       //this code is wrong.const variable is not initialized once object         
   {
    x=5;
    }
Run Code Online (Sandbox Code Playgroud)

  • ...或没有默认构造函数的类类型成员和基数. (2认同)