Скажем, я хочу сослаться на член initializer_list
, который я уже определил. Могу ли я это сделать?
Этот код компилируется и дает ожидаемое: "13 55 " как в Visual Studio, так и в gcc. знайте, что это законно:
const int foo[2] = {13, foo[0] + 42};
Скажем, я хочу сослаться на член initializer_list
, который я уже определил. Могу ли я это сделать?
Этот код компилируется и дает ожидаемое: "13 55 " как в Visual Studio, так и в gcc. знайте, что это законно:
const int foo[2] = {13, foo[0] + 42};
Итак, у нас есть агрегатная инициализация, описанная в разделе 8.5.1
проекта стандарта C++, и там говорится:
Агрегат — это массив или класс [...]
и:
Когда агрегат инициализируется списком инициализаторов, как указано в 8.5.4, элементы списка инициализаторов берутся в качестве инициализаторов для членов агрегата в порядке возрастания индекса или членов. Каждый элемент инициализируется копированием из соответствующего предложения инициализатора [...]
Хотя кажется разумным, что побочные эффекты от инициализации каждого члена агрегата должны упорядочиваться до следующего, поскольку каждый элемент в списке инициализатора является полным выражением. Стандарт на самом деле не гарантирует этого, мы можем видеть это из отчет о дефекте 1343, в котором говорится:
Текущая формулировка не указывает, что инициализация объекта, не относящегося к классу, является полным выражением, но, по-видимому, должна это делать.
а также отмечает:
Агрегатная инициализация также может включать более одного полного выражения, поэтому приведенное выше ограничение на «инициализацию неклассового объекта» неверно.
и мы можем видеть из связанного std -тема для обсуждения Ричард Смит говорит:
[intro.execution]p10: «Полное выражение — это выражение, которое не является подвыражением другого выражения. [...] Если языковая конструкция определена для создания неявного вызова функции, использование языковой конструкции считается выражением для целей настоящего определения».
Поскольку список инициализации в фигурных скобках не является выражением, и в данном случае он не приводит к вызову функции, 5 и s.i являются отдельными полными выражениями. Затем:
[intro.execution]p14: «Каждое вычисление значения и побочный эффект, связанный с полным выражением, упорядочиваются перед каждым вычислением значения и побочным эффектом, связанным со следующим полным выражением, которое необходимо оценить».
Итак, единственный вопрос: является ли побочный эффект инициализации s.i «связанным с» оценкой полного выражения «5»? Я думаю, единственное разумное предположение состоит в том, что это так: если бы 5 инициализировал член типа класса, вызов конструктора, очевидно, был бы частью полного выражения по определению в [intro.execution]p10, поэтому естественно предположить то же верно и для скалярных типов.
Тем не менее, я не думаю, что стандарт действительно где-либо прямо говорит об этом.
Так что в настоящее время это не указано в стандарте, и на него нельзя полагаться, хотя я был бы удивлен, если бы реализация не обрабатывала это так, как вы ожидаете.
Для простого случая, подобного этому, что-то подобное кажется лучшей альтернативой:
constexpr int value = 13 ;
const int foo[2] = {value, value+42};
Предложение P0507R0: Основная проблема 1343: Последовательность неклассовая инициализация поясняет поднятую точку полного выражения здесь, но не отвечает на вопрос о том, включен ли побочный эффект инициализации в оценку полного выражения. Так что это не меняет того, что это не указано.
Соответствующие изменения для этого вопроса находятся в [intro.execution]:
Составляющее выражение определяется следующим образом:
(9.1) — Составляющее выражение выражения есть это выражение.
(9.2) — Составляющие выражения списка-инициалов в фигурных скобках или (возможно, в скобках) списка-выражений являются составляющими выражениями элементов соответствующего списка.
(9.3) — Составляющие выражения инициализатора скобки-или-равно формы = инициализатор-предложения являются составляющими выражениями инициализатора-предложения. [Пример:
struct A { int x; }; struct B { int y; struct A a; }; B b = { 5, { 1+1 } };
Составные выражения инициализатора, используемые для инициализации b, равны 5 и 1+1. — конец примера]
Полное выражение — это
(12.1) — невычисленный операнд (раздел 8),
(12.2) — константное выражение (8.20),
(12.3) — декларатор инициализации (пункт 11) или мем-инициализатор (15.6.2), включая составные выражения инициализатора,
(12.4) — вызов деструктора, сгенерированного в конце жизни объекта, отличного от временного объекта (15.2), или
(12.5) — выражение, которое не является подвыражением другого выражения и не является частью полного выражения.
Таким образом, в данном случае и 13
, и foo[0] + 42
являются составными выражениями, которые являются частью полного выражения. Это отход от здесь который постулировал, что каждое из них будет своим собственным полным выражением.
Предложение по выделенной инициализации: P0329 содержит следующее дополнение, которое, кажется, делает это четко определенным:
Добавьте новый абзац в 11.6.1 [dcl.init.aggr]:
Инициализации элементов агрегата оцениваются в порядке элементов. То есть все вычисления значений и побочные эффекты, связанные с данным элементом, выполняются до вычислений любого элемента, следующего за ним по порядку.
Мы видим, что это отражено в последнем проекте стандарта.
13
и foo[0] + 42
принадлежат одному полному выражению. Так почему же побочный эффект одного инициализатора предшествует побочному эффекту другого?
- person xskxzr; 16.07.2018
, including the constituent expressions of the initializer
запятая не является отдельным пунктом.
- person Shafik Yaghmour; 16.07.2018
P0329
говорит The initializations of the elements
, а затем говорит value computations and side effects associated with a given element of the aggregate
, что не совпадает с [dcl.init.list]p4
, которое говорит о initializer-clause
и эффектах по отношению к ним.
- person Shafik Yaghmour; 20.07.2018
P0507
на самом деле не разрешил вопрос обсуждается здесь ... потому что, даже если они являются полными выражениями, они не относятся к So the only question is, is the side-effect of initializing s.i "associated with" the evaluation of the full-expression "5"?
- person Shafik Yaghmour; 20.07.2018
initializer_list
, он делает это в формате структуры, а не в формате массива. В ответах есть краткие упоминания о массивах, но все они направлены на ответы, связанные со структурой, которые (потенциально) инициализируются совершенно другим методом. На мой взгляд, это не дубликат, и я, конечно, хотел бы увидеть некоторый анализ того, является ли он законным в контексте массива. - person Jonathan Mee   schedule 20.11.2015initializer_list
, не так ли? - person Baum mit Augen   schedule 10.07.2018