因此,我知道已递增使用的变量的重用为undefined behavior in a function call。我的理解是,这在构造函数中不是问题。我的问题是关于tie
,它们之间的距离很奇怪。
鉴于:pair<int, int> func()
我可以这样做:
tie(*it++, *it) = func();
还是那不确定的行为?
答案 0 :(得分:3)
从C ++ 17开始,此代码具有未指定的行为。有两种可能的结果:
第一个参数是解引用原始迭代器的结果,第二个参数是解引用增量迭代器的结果;或
第一个参数和第二个参数都是取消引用原始迭代器的结果。
[...]参数的初始化,包括每个关联的参数 值计算和副作用,不确定地与 尊重其他任何参数。 [...]
因此tie
的第二个参数可能是取消引用增量迭代器的结果,也可能是原始迭代器的解引用。
在C ++ 17之前,情况有点复杂:
如果++
和*
都调用一个函数(例如,当it
的类型是复杂的类时),则行为是未指定,类似于自C ++ 17以来的情况;
否则,行为是未定义。
每个N4140(C ++ 14草案)[expr.call]/8:
[注意: 后缀表达式和 争论彼此之间都是无序的。 参数求值的效果先于函数 输入(请参阅[intro.execution])。 — 尾注]
因此,该代码是未定义的行为,因为一个参数的求值未与另一个参数进行排序。这两个参数的求值可能会重叠,从而导致数据争用。除非另有说明...
每个N4140 [intro.execution]/15:
在调用函数(无论函数是否为内联)时,每个 与任何参数相关的值计算和副作用 表达式,或者用后缀表达式指定被调用 函数,在执行每个表达式或 被调用函数主体中的语句。 [注意:值 与不同论点相关的计算和副作用 表达式是无序列的。 — 尾注] 每次评估 在调用函数(包括其他函数调用)中 否则在执行之前或之后专门排序 调用函数的主体相对于 9 几个 即使没有,C ++中的上下文也会导致函数调用的求值 相应的函数调用语法出现在翻译单元中。 [ 示例:对新表达式的求值调用一个或多个分配和构造函数;参见[expr.new]。为了另一个 例如,调用转换函数([class.conv.fct])可以 在没有函数调用语法出现的上下文中出现。 - 最终示例] 被调用函数的执行顺序约束(如上所述)是该函数的功能 按求值方式调用,无论调用的表达式的语法是什么 该功能可能是。
9) 换句话说,函数执行不会与每个函数交织 其他。
因此,如果运算符实际上是函数调用,则行为类似地未指定。