# 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); } 问题完美解决!