函数实参的约束是否适用于初始化列表?代码合法性问询
关于初始化列表和函数实参的求值顺序问题
咱们把问题拆开来逐一说明:
1. const int foo[] = { i++, i++ }; 是否合法?
语法上这行代码是能通过编译的(属于合法语法),但它会触发未定义行为——这才是真正需要警惕的核心问题。
原因很简单:C++标准并没有规定数组初始化列表里各个元素表达式的求值顺序,两个i++谁先执行完全由编译器自主决定。而i++会直接修改i的值,在没有明确顺序保证的前提下,对同一个对象连续执行两次修改操作,标准会将这种情况判定为未定义行为——也就是说,程序的运行结果完全不可预测,不同编译器、甚至同一编译器的不同优化等级都可能给出截然不同的输出,这绝对是你要坚决避免的写法。
2. 函数实参的要求是否适用于初始化列表?
核心规则是相通的:两者的元素/实参的求值顺序都是未指定的。
就像你提到的foo(i++, i++);会因为实参求值顺序无强制规定导致未定义行为一样,初始化列表里如果出现多个修改同一对象的表达式,同样会触发未定义行为。本质上都是因为标准没有给这些表达式的执行顺序做出明确约束,导致修改操作的先后不确定,进而引发不可预测的结果。
不过有个小细节需要区分:函数实参除了求值顺序未指定,还存在参数传递的顺序(比如栈内存的压入顺序),但初始化列表不存在这个额外维度,但这对咱们讨论的“修改同一对象的未定义行为”来说影响不大——核心矛盾始终是求值顺序无保证。
内容的提问来源于stack exchange,提问作者Jonathan Mee
相关产品推荐
相关产品推荐

