我的问题的上下文是基于堆栈的虚拟机的简化实现。我对加法和乘法运算的实现如下所示:
case OP_ADD: Push(Pop() + Pop()); break;
case OP_MUL: Push(Pop() * Pop()); break;
由于加法和乘法是可交换的运算,因此只要对第一个Pop调用(无论哪个)的副作用(即更新虚拟机的堆栈指针)进行评估,对Pop调用的评估顺序都没有关系。将在另一个Pop调用之前完成。
通过减法和除法,顺序确实重要,因此我们必须确保控制先执行哪个Pop。例如,这是减法运算的实现:
case OP_SUB: {
const auto subtrahend = Pop();
const auto minuend = Pop();
Push(minuend - subtrahend);
break;
}
我听过模糊的说法,即C ++ 17加强了序列点和排序规则,但是我没有听到任何细节。我再也没有语言律师可以在这方面自信地解析规范了。
C ++ 17中的更改是否提供足够的排序保证,使得减法可以与加法和乘法一样作为单个表达式实现? Pop()调用的顺序及其副作用是已定义,实现定义的还是未指定的?
答案 0 :(得分:6)
否。
其中一项重大更改是对某些运算符(例如shift运算符)进行了从左到右的评估,这会影响流插入。但是the subtraction operator is not included。
老实说,即使情况并非如此,我仍然会推荐您现在使用的代码,因为当人们阅读时,它显然是正确的,而这种方式永远不会依赖深奥的排序规则。