增量变量是否可在平局调用中重用?

Is an Incremented Variable Reusable in a tie Call?

所以我知道重新使用已经 post 递增的变量是 undefined behavior in a function call. My understanding is this is not a problem in constructors. My question is about tie 奇怪的是它们之间的一半。

给定:pair<int, int> func() 我可以做:

tie(*it++, *it) = func();

或者是未定义的行为?

自 C++17 起,此代码具有未指定的行为。有两种可能的结果:

  • 第一个参数是取消引用原始迭代器的结果,第二个参数是取消引用增量迭代器的结果;或

  • 第一个参数和第二个参数都是解引用原始迭代器的结果。

根据 [expr.call]/8:

[...] The initialization of a parameter, including every associated value computation and side effect, is indeterminately sequenced with respect to that of any other parameter. [...]

因此 tie 的第二个参数可能是取消引用增量迭代器或原始迭代器的结果。


在 C++17 之前,情况有点复杂:

  • 如果++*都调用一个函数(例如,当it的类型是复杂的class),那么行为是未指定,类似于自 C++17 以来的情况;

  • 否则,行为是 未定义

根据 N4140(C++14 草案)[expr.call]/8

[ Note: The evaluations of the postfix expression and of the arguments are all unsequenced relative to one another. All side effects of argument evaluations are sequenced before the function is entered (see [intro.execution]). — end note ]

因此,该代码是未定义的行为,因为一个参数的评估与另一个参数没有顺序。两个参数的评估可能会重叠,从而导致数据竞争。除非另有说明...

根据 N4140 [intro.execution]/15:

When calling a function (whether or not the function is inline), every value computation and side effect associated with any argument expression, or with the postfix expression designating the called function, is sequenced before execution of every expression or statement in the body of the called function. [ Note: Value computations and side effects associated with different argument expressions are unsequenced. — end note ] Every evaluation in the calling function (including other function calls) that is not otherwise specifically sequenced before or after the execution of the body of the called function is indeterminately sequenced with respect to the execution of the called function.9 Several contexts in C++ cause evaluation of a function call, even though no corresponding function call syntax appears in the translation unit. [ Example: Evaluation of a new expression invokes one or more allocation and constructor functions; see [expr.new]. For another example, invocation of a conversion function ([class.conv.fct]) can arise in contexts in which no function call syntax appears. — end example ] The sequencing constraints on the execution of the called function (as described above) are features of the function calls as evaluated, whatever the syntax of the expression that calls the function might be.

9) In other words, function executions do not interleave with each other.

因此,如果运算符实际上是函数调用,那么行为同样是未指定的。