Подтвердить что ты не робот

Два любопытства с грамматикой С++

В §5.2 [expr.post]/1 мы используем определение list-list

список_выражений:
      инициализатор-лист

Почему нам нужны оба определения?

В §8.5 [dcl.init]/1 мы имеем:

приготовился-INIT-лист:
      {список инициализаторов, opt}
      {}

Зачем нам нужен дополнительный , выше?

Обратите внимание, что этот фрагмент компилируется:

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

int main()
{
    A a = { 1, 2., };
}
4b9b3361

Ответ 1

Необязательная конечная запятая позволяет легко писать код, который можно продлить, не изменяя существующие строки (хорошо для управления версиями).

Например, создание массива:

int x[] = {
    1,
    2,
    3,
};

Если вы хотите добавить к нему, вы просто добавляете 4, в новую строку и вообще не изменяете строку с помощью 3,. Это не обязательно, но приятно это разрешить.

Ответ 2

Задняя запятая является наследием C, мы можем видеть это обоснованным в C99 обоснование:

K & R допускает конечную запятую в инициализаторе в конце инициализатора-лист. Стандарт сохранил этот синтаксис, поскольку он обеспечивает гибкость при добавлении или удалении членов из инициализатора список и упрощает создание таких списков.

и это также было причиной, приведенной в comp.lang.С++. moderated: Списки, разделенные запятыми, заканчивающиеся в запятой legal?:

да, это законно. и одна из причин состоит в том, чтобы сделать каждую строку синтаксически подобной, чтобы помочь автоматическим инструментам иметь дело с большими списками инициализации

Мы можем найти более подробный справочник по различным стилям инициализации в аннотированном справочном руководстве по С++ (ARM), в котором объясняются происхождение некоторые из странностей в грамматике, он говорит следующее о [dcl.init] с моим вниманием:

Есть явно слишком много обозначений для инициализаций, но каждый, кажется, хорошо обслуживает определенный стиль использования. Обоvalue = {initializer_list, opt} было унаследовано от C и хорошо служит для инициализации структур данных и массивов. [...] Обозначение выражения = также исходит из C и наиболее естественно для инициализации простых переменных, особенно для арифметики или типа указателя [...] Обозначение {expression-list} для инициализации пришел из Simula и лучше всего подходит для создания объектов типов, которые не предназначены для арифметической формы.