C ++ 11中的逗号运算符(排序)

时间:2017-09-21 10:13:23

标签: c++ c++11 c++14 language-lawyer sequencing

标准提到 f(a,(t = 3,t + 2),c); 根据我的理解,它将是赋值表达式,后跟第二个运算符的表达式。

但语法列出并列:

表达式:

赋值表达式

表达式,赋值表达式

Working Draft, Standard for Programming Language C ++ Revision N4140 (November 2014)

有人如此高兴向我解释我在这里失踪的是什么吗?

4 个答案:

答案 0 :(得分:8)

当你看到

 expression:
    assignment-expression
    expression, assignment-expression

这意味着表达有两种可能性。只有 assignment-expression 才有可能在之前的某处定义。或者以递归方式表示为 expression, assignment-expression

因此,在扩展它之后,您会收到该表达式是一个或多个赋值表达式标记的逗号分隔列表。

在示例中,您提到第二个参数是表达式(t = 3,t + 2),它由2个以逗号分隔的赋值表达式组成 - 并且因为它出现"在给出逗号的上下文中特殊含义"它必须只出现在括号中#34;。

要找出为什么赋值表达式可以采用t + 2的形式,你必须从它的定义返回并始终选择第一选择

assignment-expression
-> conditional-expression
--> logical-or-expression
---> logical-and-expression
----> inclusive-or-expression
-----> exclusive-or-expression
------> and-expression
-------> equality-expression
--------> relational-expression
---------> shift-expression
----------> additive-expression - this is what you see

答案 1 :(得分:2)

这是语法表示法(参见N4140的§1.6)。

它主要用于评估优先级,但名称可能会产生误导。

例如在[expr.ass](§5.18)中,您有以下定义:

assignment-expression:
   conditional-expression
   logical-or-expression assignment-operator initializer-clause
   throw-expression

assignment-operator: one of
   = *= /= %= += -= >>= <<= &= ^= |=

即使两项任务都没有执行任务,assignment-expression也可以是conditional-expressionthrow-expression

这只是说明a = bthrow 10cond ? c : d是具有相同优先顺序的表达式。

答案 2 :(得分:1)

请注意,由于表达式的定义是

  

表达

     

assignment-expression

     

表达式 , assignment-expression

第二行表示任何赋值表达式都可以被视为表达式,这就是t=3, t+2是有效表达式的原因。

那么为什么语法会这样呢?首先请注意,表达式的语法从最紧密绑定的类别 primary-expression 到最紧密绑定的类别表达式逐步构建。 (然后“( 表达式 )”是 primary-expression 的事实使表达式语法完整循环并让我们引起任何表达通过添加括号,比围绕它的所有东西更紧密。)

例如,众所周知的事实是二进制*比二进制+更紧密地遵循这些语法部分:

  

乘法表达

     

pm-expression

     

multiplicative-expression * pm-expression

     

multiplicative-expression / pm-expression

     

multiplicative-expression % pm-expression

     

添加剂的表达

     

multiplicative-expression

     

additive-expression + multiplicative-expression

     

additive-expression - multiplicative-expression

在表达式2 + 3 * 4中,文字234可以被视为 pm-expression ,或者也可以乘法表达式加法表达式。所以你可能会说2 + 3符合 additive-expression 的条件,但它 multiplicative-expression ,所以完整2 + 3 * 4无法以这种方式工作。相反,语法强制3 * 4被视为乘法表达式,因此2 + 3 * 4可以是添加表达式。因此,3 * 4是二进制+的子表达式。

或者在表达式2 * 3 + 4中,3 + 4可能会被视为 additive-expression ,但它不是 pm-expression ,所以这不起作用。相反,解析器必须识别2 * 3乘法表达式,它也是加法表达式,因此2 * 3 + 4是有效的 additive-expression 2 * 3作为二进制+的子表达式。

当使用两次相同的运算符或使用两个具有相同优先级的运算符时,大多数语法定义的递归性质很重要。

回到逗号语法,如果我们有令牌“a, b, c”,我们可能会说b, c可能是表达式,但它不是 assignment-expression ,因此b, c不能是整体的子表达式。相反,语法要求将a, b识别为表达式,允许将其作为另一个逗号运算符的左子表达式,因此a, b, c也是表达式a, b作为左操作数。

这对内置逗号没有任何影响,因为它的含义是关联的:“评估并放弃a,然后结果值来自评估(评估和丢弃b,然后结果值来自评估c)“与”评估和丢弃(评估并丢弃a,然后结果值来自评估b),然后结果值“相同来自评估c“。

但是在重载operator,的情况下,它确实为我们提供了明确定义的行为。给出:

struct X {};
X operator,(X, X);
X a, b, c;
X d = (a, b, c);

我们知道最后一行意味着

X d = operator,(operator,(a,b), c);

而不是

X d = operator,(a, operator,(b,c));

(我认为定义一个非关联operator,特别邪恶,但允许它。)

答案 3 :(得分:0)

 f(a,(t=3,t+2),c);

首先,将3存储到t变量中,然后使用三个参数调用函数f()。这意味着第二个参数值变为5并传递给函数。