3

因此,我了解重用已后递增的变量是函数调用中未定义的行为。我的理解是这在构造函数中不是问题。我的问题是关于tie哪个奇怪地介于两者之间。

鉴于:pair<int, int> func()我可以这样做:

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

还是那是未定义的行为?

4

1 回答 1

3

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

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

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

根据[expr.call]/8

[...] 参数的初始化,包括每个相关的值计算和副作用,相对于任何其他参数的初始化顺序是不确定的。[...]

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


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

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

  • 否则,行为是undefined

根据 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 ]

Thus, the code was undefined behavior because the evaluation of one argument was unsequenced with the other. The evaluation of the two arguments may overlap, resulting in a data race. Unless it is specified otherwise ...

Per 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.

Thus, if the operators are actually function calls, then the behavior is similarly unspecified.

于 2019-07-12T02:10:25.513 回答