为什么C++中union联合体的成员数据不会被默认初始化?
C++ union成员初始化规则解答
核心结论
union的成员不会在构造函数初始化列表阶段被自动默认初始化,这是C++标准明确规定的特性,和class/struct的初始化规则存在本质差异。
规则说明
- 普通类(class/struct)的初始化规则和你测试的一致:如果构造函数初始化列表未显式初始化某个非静态成员,也没有对应的类内初始值,该成员会被默认初始化:内置类型得到不确定值,类类型调用可访问的非删除默认构造函数。
- union的特殊初始化规则:由于union的所有成员共享同一块内存空间,同一时间仅能存在一个活跃成员,标准明确规定:
- 如果union的构造函数没有在初始化列表中显式指定初始化某一个成员
- 也没有为任何union成员设置类内初始值
那么union的所有成员都不会被执行初始化操作,类类型成员的默认构造函数不会被调用,此时该union不存在活跃成员。
对应测试用例解释
你提供的union U的默认构造函数、拷贝构造函数均未在初始化列表中指定初始化a_或i_,也没有设置类内初始值,因此a_的默认构造函数、拷贝构造函数都不会被触发,输出结果中没有A相关构造函数的打印完全符合标准要求,不属于异常行为。
另外你代码注释中关于「union存在带自定义拷贝控制成员的类类型成员时,必须显式定义构造、拷贝构造、析构函数」的理解是正确的:这种情况下C++会默认删除union的对应特殊成员函数,不显式定义则无法正常使用。
补充说明
如果需要初始化union的某个类类型成员,需要在构造函数初始化列表中显式指定,例如:
U() : a_{} { std::cout << "U()\n"; }
此时会调用A的默认构造函数,a_成为union U的活跃成员。如果后续需要切换活跃成员为i_,需要先手动调用a_.~A()析构已有的活跃成员,再通过定位new初始化i_,否则会触发未定义行为。
内容的提问来源于stack exchange,提问作者Itachi Uchiwa
相关产品推荐
相关产品推荐

