Последовательности вызовов функций в списке инициализатора конструктора?

Рассматривать:

int f () {
static int i = 0;
return i++;
}

struct Test {
int a, b;
Test () : a(f()), b(f()) {}
};

Test t;

я знаю это a инициализируется раньше b в связи с порядком их объявления в struct,

Я также знаю, что два звонка f в g(f(), f()) не секвенированы.

Так что мне интересно, если это гарантировано, что t.a == 0 а также t.b == 1?

33

Решение

Так что мне интересно, если это гарантировано, что t.a == 0 а также t.b == 1?

Это всегда будет так до тех пор, пока a приходит раньше b в объявлении класса и ничего больше не вызывает f() между инициализацией a а также b, Члены класса инициализируются в порядке их объявления в классе. [Class.base.init] / 11:

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

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

Так как a приходит раньше b затем, когда конструктор инициализирует a это позвонит f() в первый раз, а затем он будет вызывать его во второй раз, когда он инициализирует b,

Мы также знаем, что существует точка последовательности между инициализатором члена, потому что [class.base.init] / 7:

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

говорит нам, что каждый инициализатор является полным выражением, и каждое полное выражение упорядочено: [intro.execution] / 14

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

30

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

Я знаю, что a инициализируется до b из-за порядка их объявления в структуре.

Это правда.

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

Я не вижу в стандарте ничего, что говорило бы о последовательности вычислений выражений, используемых для инициализации нестатических элементов. Тем не менее, я вижу следующий пример в стандарте C ++ 11 (12.6.2 / 12):

Имена в списке выражений или в скобках-инициализаторе mem-initializer оцениваются в области действия конструктора, для которого указывается mem-initializer. [ Пример:

class X {
int a;
int b;
int i;
int j;
public:
const int& r;
X(int i): r(a), b(i), i(i), j(this->i) { }
};

Это не будет действительным, если оценка this->i секвенируется после i инициализируется.

6

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