我一直在寻找更多适合的习语std::exchange
.
今天我发现自己写这个 https://stackoverflow.com/a/74600853/85371在一个答案中:
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
.
然而,代码确实运行正确,显然是在评估lhs
first.
有人知道吗
- 标准是否保证该评估顺序
- 如果最近的标准发生了变化,哪个标准版本首先指定了它?
附言。我意识到这是一个特殊情况f(a,b)
where f
is operator!=
。我尝试使用此处找到的信息回答我自己的查询,但迄今为止未能得出结论:
- https://en.cppreference.com/w/cpp/language/eval_order https://en.cppreference.com/w/cpp/language/eval_order
- https://en.wikipedia.org/wiki/Sequence_point https://en.wikipedia.org/wiki/Sequence_point
- C++ 函数参数中的求值顺序 https://stackoverflow.com/questions/2934904/order-of-evaluation-in-c-function-parameters
- C++17 引入了哪些求值顺序保证? https://stackoverflow.com/questions/38501587/what-are-the-evaluation-order-guarantees-introduced-by-c17
C++17 引入了以下规则序列 https://en.cppreference.com/w/cpp/language/eval_order。以前的 UB 现在已经有了明确的定义。这适用于函数调用的参数以及精选的运算符:
之前排序的是一种不对称、传递、成对的关系
同一线程内的评估之间。
- 如果 A 排序在 B 之前(或者,等效地,B 排序在 A 之后),则 A 的评估将在 B 的评估之前完成
开始。
内置的!=
然而是not已测序(参见上面的链接)。函数调用将按顺序进行,但不保证计算的顺序:
- 在函数调用中,值计算和副作用
每个参数的初始化是不确定地测序与
关于任何其他参数的值计算和副作用。
(强调已添加)
根据我的阅读,即使您编写了包装函数,您的编译器也不需要评估v
首先,然后std::exchange(v, pmap[v])
最后equal(..)
。我相信,颠倒求值顺序会改变示例中的语义。
如此可悲,就像std::exchange
也就是说,在这种情况下,不能保证它会执行您需要的操作。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)