C++中f(i=-2,i=-2)与f(++i,++i)的行为变化疑问
C++函数参数求值顺序与未定义行为解析
先明确cppreference给出的C++函数参数求值核心规则:
- 在函数调用中,每个参数初始化的值计算和副作用与其他参数的值计算和副作用是不确定顺序的。
问题1:为何C++17起,f(i = -2, i = -2)不再是未定义行为?
C17之前的标准中,若在无序列点内对同一对象进行多次修改,无论最终结果是否一致,都会触发未定义行为(Undefined Behavior)。而C17重新梳理了求值顺序与内存模型的规则:函数参数的求值改为「不确定顺序」,但仅当对同一对象的修改存在冲突(即不同修改会导致不同结果)时,才会存在问题。
对于f(i = -2, i = -2),无论先计算哪个参数,两次赋值的副作用都是将i设为-2,最终i的值和两个参数的传递值完全一致,不存在冲突的修改操作。因此C++17起,这种情况属于定义良好的行为,不再是未定义行为。
注意:并非“顺序不影响结果就不属于UB”,本质是C++17消除了无冲突情况下的参数求值UB,规则本身的调整才是核心原因。
问题2:为何C++17起f(++i, ++i)是未指定行为而非直接脱离未定义行为?
++i包含两个操作:先对i执行自增的副作用,再返回自增后的值作为值计算结果。
C++17规定参数的求值顺序是不确定的,所以存在两种合法的执行路径:
- 先计算左侧
++i,再计算右侧++i:此时两个参数的值分别是i+1和i+2(最终i的值为i+2) - 先计算右侧
++i,再计算左侧++i:此时两个参数的值分别是i+2和i+1(最终i的值仍为i+2)
这两种路径的参数传递结果不同,但所有可能的结果都符合标准定义,不会出现未定义行为那种“编译器可以任意处理”的极端情况。因此它属于未指定行为(Unspecified Behavior)——标准不强制规定求值顺序,但程序的行为不会超出标准允许的范围。
内容的提问来源于stack exchange,提问作者mishar
相关产品推荐
相关产品推荐

