# C++ 初始化列表踩坑记
## 先划重点
### 初始化顺序
class CMyClass {
CMyClass(int x, int y);
int m_x;
int m_y;
};
CMyClass::CMyClass(int x, int y) : m_y(y), m_x(m_y)
{
}
>你可能以为上面的代码将会首先做`m_y=y`,然后做`m_x=m_y`,最后它们有相同的值。但是编译器先初始化`m_x`,然后是`m_y`,,因为它们是按这样的顺序声明的。结果是`m_x`将有一个不可预测的值。有两种方法避免它,一个是总是按照你希望它们被初始化的顺序声明成员,第二个是,如果你决定使用初始化列表,总是按照它们声明的顺序罗列这些成员。这将有助于消除混淆。
### 构造函数参数与成员变量重名时的情况
重名是允许的。但是需要记住:
+ 初始化列表中,括号外的是一定成员
+ 然而括号内的可以是构造函数的参数,也可以是成员
+ 如果括号内外是一样的名字,则括号内是构造函数的参数
+ 如果括号内的可以解释为是成员,也可以解释为是构造函数的参数,则优先按参数来解释
看起来很符合直觉,但情况复杂起来的时候……
## 事件经过
想写一个三角形类,用来做相交测试一类的东西。因为频繁用到三条边的`Bounding Box`,于是想在构造时先求出`Bounding Box`缓存起来。同时,不想把同样的数值储存两次,故在储存`Bounding Box`时用了引用。
于是很自信的写出来了下面的代码:
class Triangle
{
public:
Triangle(double Ax, double Ay, double Az, double Bx, double By, double Bz, double Cx, double Cy, double Cz);
private:
const double
Ax, Ay, Az,
Bx, By, Bz,
Cx, Cy, Cz;
// declare of references must go before corresponding member
// or references would be pointed to un-initialized values
const double
&ABxMin, &ABxMax,
&BCxMin, &BCxMax,
&CAxMin, &CAxMax;
double xMin, xMax;
};
Triangle::Triangle(double Ax, double Ay, double Az, double Bx, double By, double Bz, double Cx, double Cy, double Cz)
:
Ax(Ax), Ay(Ay), Az(Az), Bx(Bx), By(By), Bz(Bz), Cx(Cx), Cy(Cy), Cz(Cz),
ABxMin(Ax > Bx ? Bx : Ax), ABxMax(Ax > Bx ? Ax : Bx),
BCxMin(Bx > Cx ? Cx : Bx), BCxMax(Bx > Cx ? Bx : Cx),
CAxMin(Cx > Ax ? Ax : Cx), CAxMax(Cx > Ax ? Cx : Ax)
{
xMin = std::min(std::min(Ax, Bx), Cx);
xMax = std::max(std::max(Ax, Bx), Cx);
}
看起来很靠谱吧,然后运行时发现`ABxMin`等六兄弟解析出来全是`1.2345e-374`一类的东西。
开始以为是声明顺序的问题,然而无脑调换顺序之后还是不对。再一分析,发现第一版写的声明顺序对着呢。再换回来,自然还是不对。
继续分析,开始怀疑是`ABxMin`等六兄弟的初始化列表那里,莫非括号里面编译器给解析的是构造函数的参数?这样的话,后面用到数据的时候,这几个构造函数的参数早不存在了,引用的自然也就是野值了。于是尝试做如下更改:
Triangle::Triangle(double _Ax, double _Ay, double _Az, double _Bx, double _By, double _Bz, double _Cx, double _Cy,
double _Cz)
:
Ax(_Ax), Ay(_Ay), Az(_Az), Bx(_Bx), By(_By), Bz(_Bz), Cx(_Cx), Cy(_Cy), Cz(_Cz),
ABxMin(Ax > Bx ? Bx : Ax), ABxMax(Ax > Bx ? Ax : Bx),
BCxMin(Bx > Cx ? Cx : Bx), BCxMax(Bx > Cx ? Bx : Cx),
CAxMin(Cx > Ax ? Ax : Cx), CAxMax(Cx > Ax ? Cx : Ax)
{
xMin = std::min(std::min(Ax, Bx), Cx);
xMax = std::max(std::max(Ax, Bx), Cx);
}
问题完美解决!