C++递归程序中+=与sum=sum+x更新变量为何表现不同
问题描述
基于递归思想编写计算数字各位立方和的程序时,全局变量sum的累加逻辑出现异常:
- 使用
sum = sum + pow(sumCube(num), 3);语句更新全局变量时,计算结果无法正确累加到sum中,sum值每次都会被覆盖,表现为每次执行时sum仿佛被重置为0 - 改用
sum += pow(sumCube(num), 3);语句时程序可正常运行 - 常规认知中两种赋值写法语义完全等价,过往使用未出现过这类差异,无法定位问题诱因
复现代码
#include <iostream> #include<math.h> using namespace std; int num = 51, dgt = 0, sum = 0; int sumCube(int) { int dgt = num % 10; while (num > 10) { num = num / 10; //sum = sum + pow(sumCube(num), 3); // 运行异常 sum += pow(sumCube(num), 3); // 运行正常 } cout << sum << endl; return(dgt); } int main() { num = num * 10; sumCube(num); return 0; }
问题根因
两种写法表现不一致的核心原因是C++对普通加法赋值、复合赋值的操作数求值顺序规则不同,叠加递归调用中修改全局变量的逻辑,就触发了结果异常:
- 对于
sum = sum + pow(sumCube(num), 3);:
加法运算符+的两个操作数求值顺序没有强制规定,绝大多数编译器会按从左到右的顺序,先读取左操作数即全局变量sum的当前值(首次进入函数时该值为0,读取到的旧值会被临时存储,等待右操作数计算完成后再做加法),之后才会求值右操作数,触发sumCube(num)递归调用。递归执行过程中虽然会不断修改全局sum的值,但左操作数的值早就在递归启动前被读取为旧值,等右操作数计算完成后,最终执行的是「提前存储的旧sum值 + 本次pow计算结果」,直接覆盖了递归过程中累加得到的sum值,表现为sum每次都像被重置为0。 - 对于
sum += pow(sumCube(num), 3);:
C++标准明确规定,所有复合赋值运算符(+=/-=/*=等)必须先完整求值右侧的全部操作数——也就是先跑完所有递归调用逻辑,等递归流程中对全局sum的累加全部完成后,才会读取左侧sum的当前值,和右侧计算结果相加后写回sum,不存在提前读取旧值覆盖结果的问题,因此逻辑可以正常运行。
额外注意:代码中使用的
pow是浮点运算函数,返回值为double类型,直接转换为整数存在精度误差风险,计算整数立方建议直接使用整数乘法dgt * dgt * dgt实现,避免浮点计算错误。
内容的提问来源于stack exchange,提问作者user8718165
相关产品推荐
相关产品推荐

