[C++] "a = b + (b = a);" Vs "a = 1 + (b=a);"
最早是在微博上看到这样一个swap函数。
void swap( int & a, int & b) { a = b + 0*(b = a); } |
那么我也来讨论讨论这样的表达式有什么行为。当然这里是我认为的答案,也不敢保证完全正确,因为C++实在是太复杂了,完全不敢说知道的面面俱到。
下面来看这两个C++表达式,a和b都是int类型。
a = b + 0 * (b=a); // exp 1 a = 1 + 0 * (b=a); // exp 2 |
exp 1就是原来swap函数的实现方法,这个比较明显了。因为C++里面规定了子表达式的计算顺序和side effect的发生顺序是不确定的。
另外: "Furthermore, the prior value shall be accessed only to determine the value to be stored." 也就是说 c = c + 1;是没有问题的,因为读取c的值是为了计算最后写入c的值。
但 a = b + 0 * (b=a); 就有问题了。因为第一个读取b的操作,不是为了计算写b时用的值。所以这是一个undefined behavior。
参考这里获得C++03标准的原文(http://www.cnblogs.com/aoaoblogs/archive/2010/05/31/1748103.html)
那么exp 2呢?
a = 1 + 0 * (b=a);
一样,在C++03里面是undefined behavior。读取a的值不仅仅是为了计算写a的值。比如说可以有两种执行顺序
第一种:
1. 计算(b=a)这个表达式的值。
2. store b的值
3. 计算整个表达式的值,并store a
或者第二种:
1. 计算(b=a)这个表达式的值。
2. 计算整个表达式的值,并且store a
3. store b的值。因为这个时候a的值已经改变了,那么实际b的值就不确定了。
但是,要知道C++是一种恐怖的语言,到了C++12的时候,标准里面对于assignment加了一句话。
In all cases, the assignment is sequenced after the value computation of the right and left operands, and before the value computation of the assignment expression.
这句话不能保证exp 1的行为,因为计算+号的两个子表达式的顺序依然不确定。但是对于exp 2来说,就是well defined behavior。其执行顺序只能是这样:
1. 计算b的左值和a的右值。
2. 完成store b;
3. 完成计算(b=a)的值。
4. 计算a的左值和 1+0*(b=a) 的右值。
5. store a
6. 计算 a = 1 + 0 * (b=a) 的值。
参考这里获得更多信息(http://www.cnblogs.com/aoaoblogs/archive/2011/06/30/2094347.html)
OK,我的结论就是这样子的了。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· .NET周刊【3月第1期 2025-03-02】
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· [AI/GPT/综述] AI Agent的设计模式综述