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

Может ли ссылка инициализации массива (C/С++) сама по себе?

Мне было интересно узнать о инициализации следующей формы:

int  array[] = {
v - 1,
array[0] + 1
} ;

В инициализации второго элемента используется значение первого, но весь массив еще не инициализирован. Это происходит с компиляцией с g++, но я не знал, действительно ли это переносимая и хорошо определенная конструкция?

4b9b3361

Ответ 1

См. 3.3.2 Точка декларации:

Точка объявления для имени сразу после его полного объявления (раздел 8) и перед его инициализатор (если есть), за исключением случаев, указанных ниже. [Пример:

int x = 12;
{ int x = x; }

Здесь второй x инициализируется с его собственным (неопределенным) значением. -end пример]

Итак, вы правильно относитесь к массиву, его имя известно после =.

Затем, 8.5.1 Агрегаты:

Агрегат - это массив или класс [...]

17: Полные выражения в предложении initializer вычисляются в том порядке, в котором они появляются.

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

Ответ 2

Насколько я вижу, это не совсем понятно. В стандарте (С++ 11, 8.5.1/17) указано, что "Полные выражения в выражении инициализатора оцениваются в том порядке, в котором они отображаются", но я не вижу ничего, что требует, чтобы каждый элемент агрегата быть инициализирован из результата его инициализационного предложения до того, как будет оценен следующий.

Ответ 3

Может ли ссылка инициализации массива (C/С++) сама по себе?

Это также действительный код C.

C имеет некоторый соответствующий абзац (акцент мой).

(C99, 6.2.1p7) "Теги структуры, объединения и перечисления имеют область видимости, которая начинается сразу после появления тега в спецификаторе типа, который объявляет тег. Каждая константа перечисления имеет область, которая начинается сразу после появления его определяющий перечислитель в списке перечислений. Любой другой идентификатор имеет область видимости, которая начинается сразу после завершения его объявления."

Ответ 4

Я думаю, что это обрабатывается http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1343. Первоначально мой отчет касался только инициализаторов неклассов для объектов области пространства имен (см. Когда именно инициализатор временно уничтожен?), но проблема существует для агрегатных элементов так же хорошо, если они не относятся к классу. И, как поясняет дополнительная недавняя заметка, даже кажется, что существует и для всей агрегатной инициализации, даже если это объект класса, потому что тогда не происходит никакого вызова конструктора, который бы увеличивал полное выражение инициализатора.

Если вместо int вы использовали бы класс, а инициализация была бы вызовом конструктора, то этот вызов конструктора был бы частью одного и того же полного выражения, которое включает элемент aggregate-ininitializer, так что здесь порядок было бы хорошо, и ваш код был бы четко определен.