C++语法的两个好奇心

Bel*_*loc 13 c++ grammar language-lawyer c++14

§5.2[expr.post]/1中,我们有了expression-list的定义

expression-list:
     initializer-list

为什么我们需要这两个定义?

§8.5[dcl.init]/1中,我们有:

braced-init-list:
     {initializer-list,opt }
     {}

为什么我们需要,上面的可选项?

请注意,此代码段编译:

struct A{
    int i;
    float f;
    A(int i, float f) : i(i), f(f) {}
};

int main()
{
    A a = { 1, 2., };
}
Run Code Online (Sandbox Code Playgroud)

Sha*_*ger 19

可选的尾随逗号使您可以轻松编写可扩展的代码,而无需修改现有行(非常适合源代码控制).

例如,制作一个数组:

int x[] = {
    1,
    2,
    3,
};
Run Code Online (Sandbox Code Playgroud)

如果你想添加它,你只需添加4,一个新行,并避免修改该行3,.这没有必要,但允许它很好.

  • 同样适用于自动生成的内容(添加对最后一个元素的检查显然是微不足道的,但它不必要地使代码复杂化). (7认同)
  • @MatteoItalia:_"这显然是微不足道的补充检查的最后一个元素" _ [这并不总是正确的(/sf/ask/1444338241/到忽略-A-拖尾逗号内式设置子句邻#comment30887606_20633403) (2认同)

Sha*_*our 8

尾随逗号是C的遗产,我们可以在C99理由中看到这一点:

K&R允许在初始化列表末尾的初始化程序中使用尾随逗号.标准保留了此语法,因为它提供了从初始化列表添加或删除成员的灵活性,并简化了此类列表的计算机生成.

这也是comp.lang.c ++中引用的原因.samprated:逗号分隔的列表是否以逗号合法结尾?:

是的,这是合法的.一个原因是使每一行在语法上相似,以帮助自动工具处理大型初始化列表

我们可以在Annotated C++ Reference Manual(ARM)中找到有关不同初始化样式的更详细背景,它解释了语法中一些奇怪的起源,它说明了以下关于[dcl.init]的重点:

对于初始化,显然有太多的符号,但每个符号似乎都很好地服务于特定的使用方式.= {initializer_list,选择}符号被选自C继承和用于数据结构和数组的初始化提供良好服务.[...] =表达式表示法也来自C并且对于初始化简单变量是最自然的,尤其是算术或指针类型[...] 初始化{expression-list}表示法来自Simula并且当一个正在创建不适用于算术模具的类型的对象.