也许我不是来自这个星球,但在我看来,以下应该是一个语法错误:

int a[] = {1,2,}; //extra comma in the end

但事实并非如此。当这段代码在Visual Studio上编译时,我很惊讶,但我已经学会了不相信MSVC编译器,就c++规则而言,所以我检查了标准,它也是标准允许的。如果你不相信的话,语法规则可以参考8.5.1。

Why is this allowed? This may be a stupid useless question but I want you to understand why I am asking. If it were a sub-case of a general grammar rule, I would understand - they decided not to make the general grammar any more difficult just to disallow a redundant comma at the end of an initializer list. But no, the additional comma is explicitly allowed. For example, it isn't allowed to have a redundant comma in the end of a function-call argument list (when the function takes ...), which is normal.

那么,有什么特别的原因,这个多余的逗号是明确允许的吗?


当前回答

我认为是为了便于开发人员使用。

int a[] = {
            1,
            2,
            2,
            2,
            2,
            2, /*line I could comment out easily without having to remove the previous comma*/
          }

此外,如果出于某种原因,你有一个为你生成代码的工具;该工具不需要关心它是否是初始化中的最后一项。

其他回答

由于向后兼容的原因,我认为允许使用尾随逗号。有很多现有的代码,主要是自动生成的,它们在后面放了一个逗号。它使得在结尾没有特殊条件的情况下更容易编写循环。 如。

for_each(my_inits.begin(), my_inits.end(),
[](const std::string& value) { std::cout << value << ",\n"; });

这对程序员来说并没有什么好处。

附注:虽然这样更容易自动生成代码,但实际上我总是注意不要在后面加上逗号,这样做的工作量最小,可读性得到了提高,这是更重要的。你写了一次代码,你读了很多次。

据我所知,允许这样做的原因之一是自动生成代码应该很简单;最后一个元素不需要任何特殊处理。

原因很简单:添加/删除行很容易。

想象下面的代码:

int a[] = {
   1,
   2,
   //3, // - not needed any more
};

现在,您可以轻松地向列表中添加/删除项目,而不必有时添加/删除后面的逗号。

与其他答案相反,我真的不认为生成列表的便性是一个有效的理由:毕竟,代码对最后(或第一行)行进行特殊处理是微不足道的。代码生成器只编写一次,并使用多次。

这对机器来说更容易,比如解析和生成代码。 这对人类来说也更容易,即通过一致性进行修改、删除注释和视觉优雅。

假设C,你会这样写吗?

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    puts("Line 1");
    puts("Line 2");
    puts("Line 3");

    return EXIT_SUCCESS
}

不。不仅因为最后的语句是一个错误,而且因为它是不一致的。那么为什么对收藏也要这样呢?即使在允许省略最后分号和逗号的语言中,社区通常也不喜欢这样做。例如,Perl社区似乎不喜欢省略分号,除了一行程序。他们也把这个应用到逗号上。

不要在多行集合中省略逗号,就像不要在多行代码块中省略分号一样。我是说,即使语言允许,你也不会这么做,对吧?对吧?

每个人都说添加/删除/生成行很容易,但这种语法真正的亮点是合并源文件。假设你有这样一个数组:

int ints[] = {
    3,
    9
};

假设您已经将这段代码签入存储库。

然后你的朋友编辑它,在结尾添加:

int ints[] = {
    3,
    9,
    12
};

你同时编辑它,在开头加上:

int ints[] = {
    1,
    3,
    9
};

从语义上讲,这些类型的操作(添加到开头,添加到结尾)应该是完全合并安全的,你的版本控制软件(最好是git)应该能够自动合并。遗憾的是,情况并非如此,因为你的版本在9后面没有逗号,而你朋友的版本有。然而,如果最初的版本后面有9,他们就会自动生成。

因此,我的经验法则是:如果列表跨越多行,则使用尾随逗号,如果列表在单行上,则不要使用尾随逗号。