C++中a=a+deg1(&a)运行结果为40而非20的原因解析
问题根因
你得到40的结果不是编译器错误,是C++表达式求值规则和函数副作用共同导致的,具体拆解如下:
核心代码执行流分析
先看deg1函数的逻辑:
int deg1(int*p){ *p = 20; // 直接修改指针指向的原变量,副作用会立刻生效 int i = *p; return i; // 固定返回20 }
关键问题出在a = a + deg1(&a);这行:
- 在C++17标准正式发布前,加法运算符
+的左右两个操作数的求值顺序是未指定的:编译器可以自由选择先读左边的a,还是先执行右边的deg1(&a)函数调用,两种执行顺序都符合语言标准。 - 你当前使用的编译器选择了先执行右侧的函数调用,具体执行步骤为:
- 第一步:调用
deg1(&a),进入函数后直接把原变量a的值从初始的10修改为20,函数最终返回值为20 - 第二步:读取加法左侧操作数
a的值,此时a已经被deg1的副作用修改为20,不再是初始的10 - 第三步:执行加法运算:20 + 20 = 40,将结果赋值给a,因此最终输出a的值为40
- 第一步:调用
如果你换用其他选择了“先读左操作数再调用函数”的旧编译器,这行代码会得到10+20=30的结果,这同样是符合标准的,不存在对错,只说明这类代码本身存在歧义,属于不良实践。
为什么b的计算结果符合预期
你写的b = b +deg2(b);结果固定为60,不会出现歧义,原因是deg2是值传递:
int deg2(int x){ return x * 2; // 操作的是b的拷贝x,不会修改原变量b }
不管编译器先读b的值,还是先调用deg2,原变量b的值始终是初始的20,deg2固定返回40,求和结果永远是20+40=60,不会出现不确定的结果。
编码建议
不要在同一个表达式中,既通过指针/引用的副作用修改某个变量,又在表达式的其他位置读取这个变量的值,这类代码会依赖编译器的求值顺序选择,极易出现和预期不符的运行结果,可维护性极差。
内容的提问来源于stack exchange,提问作者YarrakVar
相关产品推荐
相关产品推荐

