C ++初始化列表 - 我不明白

时间:2011-03-01 10:23:34

标签: c++ initialization-list

在Effective C ++中,据说初始化列表中的数据元素需要按其声明的顺序列出。进一步说,其原因是数据元素的析构函数以其构造函数的相反顺序调用。

但我只是看不出这是怎么回事......

6 个答案:

答案 0 :(得分:25)

请考虑以下事项:

class Class {
    Class( int var ) : var1( var ), var2(var1 ) {} // allright
    //Class( int var ) : var2( var ), var1(var2 ) {} // var1 will be left uninitialized

    int var1;
    int var2;
};

第二个(已注释掉的)构造函数看起来很好,但实际上只会初始化var2 - var1将首先初始化,并且将使用尚未编译的var2进行初始化在那时初始化。

如果按照与成员变量相同的顺序列出初始化程序,则在类声明中列出此类错误的风险会降低很多。

答案 1 :(得分:10)

当成员也是某种以某种方式相互依赖的类的对象时,构造和破坏的顺序可能很重要。

考虑一个简单的例子:

class MyString {
public:
  size_t s_length;
  std::string s;
  MyString(const char *str) : s(str), s_length(s.length()) {}
};

此示例中的意图是成员s_length保存存储字符串的长度。但是,这不起作用,因为s_length将在 s之前初始化。因此,在执行s.length的构造函数之前调用s

答案 2 :(得分:7)

例如,如果您有这样的类:

class X {
  int a,b;
  X(int i) : b(i),a(b) { } // Constructor
};

类X的构造函数看起来首先初始化“b”,但它实际上是按声明的顺序初始化。这意味着它将首先初始化“a”。然而,“a”初始化为尚未初始化的“b”值,因此“a”将获得垃圾值。

答案 3 :(得分:3)

破坏与构造相反,因此元素以相反的顺序被破坏。

我们说我们有2名成员,abb取决于a,但a不依赖于b

当我们构建时,我们首先构造a,现在它存在,我们可以构造b。当我们破坏时,如果我们首先破坏a这将是一个问题,因为b取决于它。但我们首先破坏b并确保完整性。

这是典型的。例如,在群论中,fg的倒数是~g~f(其中~ff的倒数)

当你穿着时,你首先穿上袜子,然后穿上鞋子。当你脱衣服时,先脱掉鞋子,然后取下袜子。

答案 4 :(得分:2)

如果您的成员的一个构造函数抛出异常,这也可能是一个问题。然后,所有已经正确构造的成员必须以某些顺序进行破坏,因为没有类似于析构函数的初始化列表。此顺序与类声明中成员的外观相反。一个例子:

#include <iostream>

struct A1 {
  A1(int) { std::cout << "A1::A1(int)" << std::endl; }
  ~A1() { std::cout << "A1::~A1()" << std::endl; }
};

struct A2 {
  A2(int) { std::cout << "A2::A2(int)" << std::endl; }
  ~A2() { std::cout << "A2::~A2()" << std::endl; }
};

struct B {
  B(int) { std::cout << "B::B(int)" << std::endl; throw 1; }
  ~B() { std::cout << "B::~B()" << std::endl; }
};

struct C {
  C() : a1(1), a2(2), b(3) { std::cout << "C::C()" << std::endl; } // throw 1; }
  ~C() { std::cout << "C::~C()" << std::endl; }
  A1 a1;
  A2 a2;
  B b;
};

int main() {
  try {
    C c;
  } catch (int i) {
    std::cout << "Exception!\n";
  }
}

输出将是这样的:

A1::A1(int)
A2::A2(int)
B::B(int)
A2::~A2()
A1::~A1()
Exception!

答案 5 :(得分:1)

  

进一步说是推理   对于这是数据的析构函数   元素被反向调用   他们的建设者的顺序。

请参阅Steve Jessop在Class component order of initialisation

的评论