hjk41的日志

Avatar

Effective C++ 笔记13: 成员变量的初始化顺序

看看下面的代码:

template<class T>
class Array {
public:
  Array(int lowBound, int highBound);
  ...
private:
  vector<T> data;               // the array data is stored
                                // in a vector object; see
                                // Item 49 for info about
                                // the vector template
  size_t size;                  // # of elements in array
  int lBound, hBound;           // lower bound, higher bound
};
template<class T>
Array<T>::Array(int lowBound, int highBound)
: size(highBound - lowBound + 1),
  lBound(lowBound), hBound(highBound),
  data(size)
{}


这是一个有上下界的数组,constructor 的初始化列表中对各个成员变量进行了初始化。但是这样会出错,因为C++总是按成员变量在类声明中出现的顺序来初始化成员变量的。在这里,这个顺序就是 data -> size -> lBound -> hBound,所以在初始化 data 时 size 还没有被初始化,也就是说,我们并不知道 data 到底会是一个多大的 vector。
为什么C++不按初始化列表的顺序来初始化成员变量呢?因为我们知道初始化的顺序应该与析构的顺序相反,也就是说,如果有两个成员变量 A 和 B ,初始化顺序为 A -> B ,那么在这个类被析构时,应该先析构 B 再析构 A。而对一个类来说 constructor 可能有多个,初始化列表也会有多个,所以如果我们要按初始化列表的顺序来进行初始化,那么我们就得记住这个顺序,以便在析构时决定析构的顺序。所以C++就选择了简单的点的方法,按成员变量出现的顺序来初始化。
既然如此,我们在写初始化列表时最好按成员变量出现的顺序来写,这样不容易出现混淆。

早上听了 Bjarne 的讲座,一到会场,果然就是我事先见到的那个老头……
老头子长得挺可爱的,脑袋上的头发掉得差不多了,就剩周围一圈。印象最深的是他在说现在的C++教材时,他说他很讨厌现在的这些教材,他们都花一两章来说那些 float int 之类的东西,他说 "If that is C++, I don't like it either."

Thank you for your information.
but what if class A, for example, contains other objects as data members, will those data member objects call their own constructors before executing code inside the constructor of class A, A::A()?

3ks.

评论已关闭