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