Создает ли приращение в списке инициализатора члена неопределенное поведение?

Это вызывает неопределенное поведение? В частности, увеличение в списке инициализатора и как это будет оцениваться.

class Wrinkle {
public:
Wrinkle(int i) : a(++i), b(++i), x(++i) {}
private:
int a;
int x;
int b;
};

Различие в порядке между объявлением членов и списком инициализаторов предназначено, так как это пример, который продемонстрировал бы именно эту разницу, поэтому, пожалуйста, пока игнорируйте это.

24

Решение

Это не генерирует Неопределенное поведение так как:

[Class.base.init] # 7

[ Замечания: Инициализация, выполняемая каждым mem-initializer, представляет собой полное выражение. Любое выражение в mem-initializer оценивается как часть полного выражения, которое выполняет инициализацию. ]

[Intro.execution]

5. Полное выражение

  • […]
  • init-декларатор или mem-initializer, включая составные выражения инициализатора,

9. Каждое вычисление значения и побочный эффект, связанный с полным выражением, упорядочивается перед каждым вычислением значения и побочным эффектом, связанным со следующим полным выражением, которое будет оценено.


Но будьте осторожны, что:

[Class.base.init] # 13

В не делегирующем конструкторе инициализация происходит в следующем порядке:

  • […]
  • Затем не статические члены данных инициализируются в порядке, в котором они были объявлены в определении класса (опять же, независимо от порядка mem-инициализаторов).

Таким образом, ваш код будет эффективно назначать i + 1 в a, i + 2 в x а также i + 3 в b,

31

Другие решения

Стандарт C ++ 17 содержит пример почти так же, как в вопросе:

struct B1 { B1(int); /* ... */ };
struct B2 { B2(int); /* ... */ };
struct D : B1, B2 {
D(int);
B1 b;
const int c;
};

D::D(int a) : B2(a+1), B1(a+2), c(a+3), b(a+4) { /* ... */ }
D d(10);

Далее следует примечание:

[Примечание: инициализация, выполняемая каждым mem-initializer, составляет полное выражение (4.6). Любое выражение в mem-initializer оценивается как часть полного выражения, которое выполняет инициализацию. — конец примечания]

Перейдя по ссылке, раздел 4.6 сообщает нам, что один из Определения «полного выражения»

… mem-initializer, включая составные выражения инициализатора,

Фраза «в том числе составные выражения initiailizer» настоятельно предполагает мне, что приведенный выше код является законным, потому что побочные эффекты ++i будет завершено, прежде чем перейти к следующему инициализатору. Это всего лишь мое прочтение стандарта, хотя я с радостью полагаюсь на любого, у кого больше опыта, чем у меня.

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

6

По вопросам рекламы [email protected]