C++中v != std::exchange(v, pmap[v])的求值顺序是否有标准保证?
关于
std::exchange与operator!=求值顺序的疑问 我发现越来越多适合使用std::exchange的编程写法。今日我在回答中写出了如下代码:
do { path.push_front(v); } while (v != std::exchange(v, pmap[v]));
相比如下写法,我更喜欢上面的版本:
do { path.push_front(v); if (v == pmap[v]) break; v= pmap[v]; } while (true);
原因想必不言而喻。但我不太熟悉标准术语,不禁担心lhs != rhs不能保证左操作数先于右操作数求值,这会导致比较恒为true。不过实际代码运行正常,似乎是先求值左操作数。
请问:
- C++标准是否保证该求值顺序?
- 若该规则在近年标准中有变化,首个规定此内容的标准版本是哪个?
注:我意识到这是f(a,b)(其中f为operator!=)的特殊情况,我已尝试查阅相关资料但尚未得出结论。
问题1解答
C++标准保证operator!=的左操作数会先于右操作数求值。对于内置的比较运算符(包括!=),左操作数属于顺序点前的求值项,必须在右操作数计算完成前完成求值。也就是说,v != std::exchange(v, pmap[v])中会先获取左边v的原始值,再执行右边的std::exchange(此时修改v的值),比较的是修改前的v和pmap[v]的值,逻辑完全正确。
问题2解答
这个求值顺序规则是在C++17中首次被明确标准化的。在C17之前,除了&&、||和逗号运算符这类原本就有顺序保证的运算符外,大多数二元运算符(包括!=)的左右操作数求值顺序是未指定的,编译器可自由选择求值顺序。但从C17开始,所有内置二元运算符都被规定为左操作数先求值,再处理右操作数。因此你的代码在C17及以后版本中行为确定,而在C17之前,这段代码的行为属于未定义(尽管很多编译器可能按左先右后的顺序实现,但标准不做强制保证)。
内容的提问来源于stack exchange,提问作者sehe
相关产品推荐
相关产品推荐

