在以下代码中:
A & getDataA() ;
B & getDataB() ;
void foo()
{
getDataA() = getDataB() ;
}
是否getDataA()
保证在getDataB()
之前或之后进行评估,或者两个操作数的评估是否与其他操作数无关?
注意:我对引用该标准的答案感兴趣。
我试着理解找到答案的标准,这是我研究的结果。我的理解是对这两个操作数的评估是不合理的。
但是......(每个引用来自C ++ 14 draft n3797,5.17 [expr.ass]):
赋值运算符(=)和复合赋值运算符从右到左分组。
这意味着表达式a = b = c ;
实际上是a = (b = c) ;
。
在所有情况下,赋值在右和左操作数的值计算之后,以及赋值表达式的值计算之前排序。
第一部分说明对于a = b ;
,实际的分配将在评估a
和b
之后进行。第二部分让我感到困惑:我可以理解operator +=
(或另一个复合赋值运算符),但我无法理解operator =
。
看一下章节的开头(5 Expression [expr]),我读到了:
重载运算符的使用转换为函数调用,如13.5中所述。重载运算符遵循第5章中指定的语法规则,但操作数类型,值类别和评估顺序的要求被函数调用的规则替换。
这使得我相信对于A
或B
不是内置函数的情况,对两个操作数的评估没有排序(对函数参数的评估没有排序,除非我遗漏了一些内容)
但在上面的情况中,A
和B
可能是int
,因此内置的operator =
将被调用,而不是函数。
答案 0 :(得分:5)
考虑§1.9中的这段文字:
C ++中的几个上下文导致函数调用的评估,甚至 虽然没有相应的函数调用语法出现在 翻译单位。 [...]对执行的排序约束 被调用函数(如上所述)是函数的特征 无论调用表达式的语法如何,都会调用 功能可能是。
这特别适用于[expr] / 2的以下引文(你也引用过自己):
重载运算符遵循第5章中指定的语法规则, 但 操作数类型,值类别和评估的要求 订单被函数调用规则替换。
假设A
是一个类,赋值是对operator=
的隐式调用:
getDataA().operator=( getDataB() );
根据[expr.call] / 8的一份(非规范性)说明:
[注意:后缀表达式和参数的评估 表达式相对于彼此都是无序的。 [...] - 结束记录]
规范性文本,在本答案的最初引用之上,包含了这一含义:
除非另有说明,否则评估各个运营商的操作数 并且个别表达的子表达式没有被排除。
关于参数的评估顺序和函数调用中的后缀表达式,没有任何注意事项。