8

如果你看到这段代码,

class A{
public:
    A(int a):var(a){}
    int var;
};

int f(A obj) {
    return obj.var;
}

int main() {
    //std::cout<<f(23);    // output: 23
    std::cout<<f(23, 23);  // error: too many arguments to function 'int f(A)'
    return 0;
}

f(23, 23)无法编译,因为逗号在这里充当分隔符而不是逗号运算符。

逗号在哪里不能用作逗号运算符?还是反过来?

4

5 回答 5

11

从语法的角度来看,函数调用的参数在括号内形成一个可选的表达式列表。表达式列表由一个或多个用逗号分隔的赋值表达式组成。逗号只能表示需要表达式的逗号运算符。

逗号运算符由一个expression、 a和一个assignment-expression组成一个表达式,但一个涉及逗号运算符的表达式本身并不是一个赋值表达式,因此不能出现在一个表达式列表中,除非它是某个事物的组成部分是一个赋值表达式,

例如,您可以将任何表达式(包括使用逗号运算符的表达式)括在括号内,以生成作为赋值表达式并因此在表达式列表中有效的表达式。

例如

后缀表达式,其中表达式列表由两个赋值表达式组成,每个赋值表达式都是一个标识符

f( a, b );

后缀表达式,其中表达式列表由单个赋值表达式组成,它是主表达式,它是使用逗号运算符的括号表达式。

f( (a, b) );
于 2010-06-27T18:35:42.773 回答
8

逗号标记作为运算符的使用不同于它在函数调用和定义、变量声明、枚举声明和类似构造中的使用,在这些构造中它充当分隔符。

维基百科 - 逗号运算符

于 2010-06-27T18:24:49.237 回答
8

我对标准草案进行了搜索。基本上,在语法中,-list产生式是用逗号分隔不同项目的产生式。以下结果是 C++03 特定的。在 C++0x 中,表达式列表直接委托给初始化器列表,因为在 C++0x 中,大括号列表同样可以出现在函数和构造函数参数中。

  • 表达式列表用于函数/构造函数参数(包括函数转换)
  • enumerator-list 枚举的列表
  • init-declarator-list在一个声明中声明的不同名称

    例子:

    int a, b;
    
  • parameter-declaration-list函数参数声明列表(惊喜!)
  • 初始化列表列表类似于表达式列表,但可以包括大括号表达式列表。用于聚合初始化(初始化数组或结构)
  • member-declarator-list类似于 init 声明器列表,但用于类中的成员声明

    例子:

    struct A { int a, b; };
    
  • base-specifier-list的基类列表。
  • mem-initializer-list成员初始化列表

    例子:

    struct A { A():a(0), b(0) { } int a; int b; };
    
  • template-parameter-list模板参数声明列表。
  • template-argument-list传递给模板的模板参数列表。
  • type-id-list异常规范的类型列表

    例子:

    void f() throw(int, bool) { }
    

宏参数也有一个标识符列表,我没有在那个列表中,因为它实际上是预处理器语法的一部分。

于 2010-06-27T21:51:39.690 回答
7

这与表达式的语言定义有关,这是相当复杂的。

f(1, 2)是一个有两个参数的函数调用表达式。相反,f((1, 2))是一个带有一个参数的函数调用表达式,即子表达式1, 2,其计算结果为 2。

于 2010-06-27T18:30:40.000 回答
1

逗号运算符始终充当逗号运算符,但逗号并不总是表示逗号运算符 - 有时它只是标点符号。

至于什么时候是标点符号,简单的回答是“当标准这么说的时候”。经历标准所说的所有情况会给出更长的答案 - 但不太可能更有用,因为(例如)它必须处理大多数人不太关心的一些极端情况关于。

于 2010-06-27T18:29:47.753 回答