【问题标题】:What is the sequencing of the operands of operator = in C++?C++中operator =操作数的顺序是什么?
【发布时间】:2014-12-28 23:08:22
【问题描述】:

在以下代码中:

A & getDataA() ;
B & getDataB() ;

void foo()
{
   getDataA() = getDataB() ;
}

getDataA() 是否保证在 getDataB() 之前或之后进行评估,或者两个操作数的评估相对于另一个而言是无序的?

注意:我对引用标准的答案感兴趣。

.

P.S.:我的研究到目前为止......

我试图了解标准以找到答案,这是我的研究结果。我的理解是两个操作数的求值是无序的。

但是...(每个引用都来自 C++14 草案 n3797, 5.17 [expr.ass]):

赋值运算符 (=) 和复合赋值运算符都从右到左分组。

这意味着表达式a = b = c ; 真的是a = (b = c) ;

在所有情况下,赋值顺序在左右操作数的值计算之后,赋值表达式的值计算之前。

第一部分说对于a = b ;,实际分配将在评估ab 之后发生。第二部分让我感到困惑:operator +=(或其他复合赋值运算符)我可以理解,但operator = 无法理解。

看着本章的开头(5 表达式 [expr]),我读到:

重载运算符的使用被转换为函数调用,如 13.5 所述。重载的运算符遵循第 5 章规定的语法规则,但操作数类型、值类别和求值顺序的要求被函数调用规则所取代。

这就是让我相信在 AB 不是内置的情况下,两个操作数的计算是未排序的(函数参数的计算是未排序的,除非我遗漏了什么)。

但在上面的例子中,AB 可能是int,所以会调用内置的operator =,而不是函数。

【问题讨论】:

  • 这两个函数调用是顺序不确定的:这意味着一个发生在另一个之前,但没有指定哪一个。至于你觉得莫名其妙的部分:规则实际上是说,在a=(b=c) 中,分配给b 发生在分配给a 之前(实际分配在ab=c 都被评估之后排序; 并且b=c 的值是在分配b 之后计算的)。
  • @IgorTandetnik : 你能找到使operator = 的操作数评估不确定排序的标准引用吗?
  • 1.9/15 除非另有说明,否则对单个运算符的操作数和单个表达式的子表达式的求值是无序的...调用函数中的每个求值(包括其他函数调用) ) 在被调用函数的主体执行之前或之后没有特别排序的,相对于被调用函数的执行是不确定的。
  • 到目前为止,您的评论在@Loopunroller 之后到达了一点,但更准确。如果你写一个实际的答案,我真的会考虑选择它...... :-)
  • 其实答案取决于AB的性质。在您的示例中,这些看起来像类,因此= 不一定是内置运算符,而是对重载operator= 的调用。这将使您引用的部分 5 部分不适用。我想这不是你的本意?

标签: c++ standards c++14


【解决方案1】:

考虑 §1.9 中的这段文字:

C++ 中的多个上下文会导致对函数调用进行求值,甚至 虽然没有对应的函数调用语法出现在 翻译单元。 […] 执行的顺序限制 被调用的函数(如上所述)是函数的特征 无论调用的表达式的语法是什么,都按评估调用 功能可能是。

这特别适用于 [expr]/2 的以下引用(您也引用了自己):

重载的操作符遵守第 5 条中规定的语法规则, 但要求操作数类型、值类别和求值 顺序被函数调用的规则代替

假设A是一个类,赋值是对其operator=的隐式调用:

getDataA().operator=( getDataB() );

根据 [expr.call]/8 中的(非规范性)注释:

[ 注意: 后缀表达式和参数的求值 表达式彼此之间都是无序的。 […] —结束注释 ]

在此答案的初始引用上方找到的规范文本隐含地包含以下内容:

除非另有说明,否则对单个运算符的操作数进行求值 和单个表达式的子表达式是无序的。

没有任何关于函数调用中参数的求值顺序和后缀表达式的说明。

【讨论】:

    猜你喜欢
    • 2022-11-29
    • 2018-07-06
    • 1970-01-01
    • 2011-01-16
    • 2020-06-27
    • 2010-10-14
    • 1970-01-01
    • 1970-01-01
    • 2011-01-16
    相关资源
    最近更新 更多