C++中能否用刚初始化的成员变量初始化其他成员变量?
1. 能否在初始化a后立即读取其值初始化b
你给出的示例代码里完全可以这么写。这里有个很多开发者容易踩的核心规则:C++类非静态成员的初始化顺序,根本不看你在构造函数初始化列表里书写的先后,只看成员在类定义中的声明顺序,谁先声明谁先完成初始化。
你的代码里a在b前面声明,所以初始化时会先执行a(1)完成a的赋值,再执行b(a+1),此时读取a的值是完全合法的操作。要是后续调整代码时把类里b的声明挪到a前面,哪怕初始化列表里还是先写a(1)再写b(a+1),实际执行时也会先初始化b——这时候a还处于未初始化状态,读取它的值属于未定义行为,出现什么结果都不奇怪。
2. 是否受C++11标准明确保证、可跨编译器稳定生效
这个初始化顺序规则不是C11新增的,从最早的C98标准开始就有明确规定,C11及后续所有版本的标准都保留了该规则:所有符合标准的C编译器必须严格按照成员声明顺序执行初始化,不存在自定义实现的空间。只要你保证被读取的成员在类中声明顺序早于待初始化的成员,这个写法可以在所有兼容编译器下稳定生效,不存在行为差异。
实用提示:GCC、Clang、MSVC等主流编译器都提供
-Wreorder编译警告,当你初始化列表的书写顺序和成员声明顺序不一致时会触发提示,这个警告不要随意关闭,能帮你避开绝大多数初始化顺序相关的隐蔽bug。
3. 该初始化方式是否存在副作用
这个写法本身没有任何隐式副作用,和先初始化a、再在构造函数体内给b赋值的运行效果完全一致。唯一的风险来自代码维护阶段的人为失误:如果后续修改代码的人不清楚初始化顺序规则,调整了类中成员的声明顺序却没有同步调整初始化逻辑,就会触发前面提到的未定义行为,这类问题如果没有编译警告提示,排查成本很高。
你提供的示例代码如下,是完全符合C++标准的合法写法,运行后a的值为1,b的值为2:
class X { public: int a; int b; X() : a(1), b(a+1) {} };
内容的提问来源于stack exchange,提问作者robert

