为何arr[i] = ++i这类数组赋值在C++与JavaScript中表现不同?
为什么
arr[i] = ++i在C++和JavaScript中行为不同? 先看你给出的两段测试代码:
C++代码:
int arr[] = {0,0}; int i = 0; arr[i] = ++i; cout << arr[0] << ',' << arr[1] << endl; // 输出为0,1
JavaScript代码:
let arr = [0,0] let i = 0 arr[i] = ++i console.log(arr) // 输出为[1,0]
JavaScript的行为(完全确定)
JavaScript对表达式执行顺序有严格的从左到右规则:
- 先计算赋值操作左侧的
arr[i]:此时i的值为0,确定要赋值的位置是数组第0位。 - 再计算右侧的
++i:将i自增为1,同时返回这个新值1。 - 最后把右侧结果1赋值给之前确定的
arr[0],所以数组最终是[1,0],和你看到的输出一致。
C++的情况(注意:属于未定义行为)
你看到的0,1只是特定编译器下的结果,C++标准并没有规定这段代码的行为。因为在C++中,同一个表达式里对变量i既做读取(计算数组索引)又做修改(++i),且两个操作之间没有序列点(sequence point),这种场景属于未定义行为——不同编译器、甚至同一编译器不同优化级别都可能输出不同结果。
你遇到的这个结果,是因为该编译器选择先执行右侧的++i,把i变为1,再用这个新值计算左侧数组索引,也就是给arr[1]赋值1,arr[0]保留初始的0,所以输出0,1。但换个编译器,完全可能和JavaScript的结果一致,甚至出现其他奇怪输出,这都是标准允许的。
差异的根源
两种语言的表达式求值规则差异导致了这个结果:
- JavaScript强制要求表达式从左到右依次求值,每一步结果都确定。
- C++为了给编译器留足优化空间,允许在无序列点的情况下,对表达式子部分进行任意顺序求值,因此这种同时读写同一变量的代码行为完全不可控。
另外你觉得C的表现更符合直觉,但这只是特定编译器的行为,本质上这段C代码是不规范的,实际开发中绝对要避免写这类代码。
内容的提问来源于stack exchange,提问作者Yucheng Zhou
相关产品推荐
相关产品推荐

