1. 代码结构分析
cpp
class Test
{
public:
Test(int data=100) : mb(data), ma(mb) {}
void show() { cout << "ma:" << ma << " mb:" << mb << endl; }
private:
int ma;
int mb;
};
int main()
{
Test t1;
t1.show();
return 0;
}
- 类定义 :
Test类包含两个私有成员ma和mb,以及一个带默认参数的构造函数和一个打印函数。 - 构造函数 :使用了初始化列表,看起来是先初始化
mb,再用mb初始化ma。 - 主函数 :创建了一个
Test对象t1,并调用show()打印成员变量。
2. 关键问题:初始化顺序
在C++中,成员变量的初始化顺序由它们在类中的声明顺序决定,而不是初始化列表中的顺序。
- 在类的声明中,
int ma;出现在int mb;之前。 - 因此,构造函数初始化列表的实际执行顺序是:
- 先初始化
ma,使用的是mb的值,但此时mb还未被初始化,是一个随机的垃圾值。 - 然后初始化
mb,将其赋值为data(即100)。
- 先初始化
3. 运行结果
当执行 t1.show() 时,输出结果是未定义的:
mb的值是确定的,为 100。ma的值是未定义的,它是在mb初始化之前就被赋值的垃圾值,无效值,-958993460,0xcc
4. 正确的写法
为了避免这种问题,应该确保初始化列表的顺序与成员声明顺序一致,或者避免在初始化一个成员时使用另一个未初始化的成员。
cpp
class Test
{
public:
// 修正:先初始化mb,再用mb初始化ma,同时保证声明顺序一致
Test(int data=100) : mb(data), ma(mb) {}
private:
int mb; // 调整声明顺序,先声明mb
int ma;
};
或者更稳妥地直接使用参数初始化:
cpp
Test(int data=100) : ma(data), mb(data) {}
总结
这段代码的核心问题在于成员变量的初始化顺序与初始化列表顺序不一致 ,导致 ma 被初始化为一个未定义的值。这是C++中一个常见的陷阱,需要特别注意。