Это вызывает неопределенное поведение? В частности, увеличение в списке инициализатора и как это будет оцениваться.
class Wrinkle {
public:
Wrinkle(int i) : a(++i), b(++i), x(++i) {}
private:
int a;
int x;
int b;
};
Различие в порядке между объявлением членов и списком инициализаторов предназначено, так как это пример, который продемонстрировал бы именно эту разницу, поэтому, пожалуйста, пока игнорируйте это.
Это не генерирует Неопределенное поведение так как:
[ Замечания: Инициализация, выполняемая каждым mem-initializer, представляет собой полное выражение. Любое выражение в mem-initializer оценивается как часть полного выражения, которое выполняет инициализацию. ]
5. Полное выражение
- […]
- init-декларатор или mem-initializer, включая составные выражения инициализатора,
9. Каждое вычисление значения и побочный эффект, связанный с полным выражением, упорядочивается перед каждым вычислением значения и побочным эффектом, связанным со следующим полным выражением, которое будет оценено.
Но будьте осторожны, что:
В не делегирующем конструкторе инициализация происходит в следующем порядке:
- […]
Затем не статические члены данных инициализируются в порядке, в котором они были объявлены в определении класса (опять же, независимо от порядка mem-инициализаторов).
Таким образом, ваш код будет эффективно назначать i + 1
в a
, i + 2
в x
а также i + 3
в b
,
Стандарт 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
будет завершено, прежде чем перейти к следующему инициализатору. Это всего лишь мое прочтение стандарта, хотя я с радостью полагаюсь на любого, у кого больше опыта, чем у меня.
(Стоит также отметить, что инициализация членов будет происходить в том порядке, в котором они объявлены в классе, а не в том порядке, в котором они появляются в списке инициализаторов членов).