valores una todas tipos retornan que llamar lenguaje las funciones funcion ejemplos como c++ language-lawyer undefined-behavior order-of-evaluation initialization-order

c++ - una - ¿Están las llamadas de funciones en la lista de inicializadores del constructor secuenciadas?



tipos de funciones en lenguaje c (2)

Considerar:

int f () { static int i = 0; return i++; } struct Test { int a, b; Test () : a(f()), b(f()) {} }; Test t;

Sé que a se inicializa antes de b debido al orden de su declaración en la struct .

También sé que las dos llamadas a f in g(f(), f()) se han seguido.

Entonces, me pregunto si se garantiza que ta == 0 y tb == 1 ?


Entonces, me pregunto si se garantiza que ta == 0 y tb == 1 ?

Esto siempre será cierto siempre que a venga antes de b en la declaración de clase y nada más llame a f() entre la inicialización de b . Los miembros de la clase se inicializan en el orden en que se declaran en la clase. [class.base.init] / 11:

En un constructor no delegante, la inicialización procede en el siguiente orden: [...]

  • Luego, los miembros de datos no estáticos se inicializan en el orden en que se declararon en la definición de clase (nuevamente, independientemente del orden de los iniciadores de memoria).

Entonces, como a viene antes de b , cuando el constructor inicializa a , llamará a f() la primera vez y luego la invocará una segunda vez cuando inicialice b .

También sabemos que hay un punto de secuencia entre el inicializador de miembro porque [class.base.init] / 7:

[...] La inicialización realizada por cada mem-initializer constituye una expresión completa. Cualquier expresión en un inicializador de memoria se evalúa como parte de la expresión completa que realiza la inicialización.

nos dice que cada inicializador es una expresión completa y cada expresión completa está secuenciada: [intro.execution] / 14

Cada cómputo de valor y efecto secundario asociado con una expresión completa se secuencia antes de que se evalúe cada cálculo de valor y efecto secundario asociado con la siguiente expresión completa.


Sé que a se inicializa antes de b debido al orden de su declaración en la estructura.

Es verdad.

Mi interpretación de esa restricción es que a no se puede inicializar antes de b menos que la evaluación de la expresión del inicializador se complete antes de que b se inicialice.

No veo nada en el estándar que explique la secuencia de la evaluación de las expresiones utilizadas para inicializar miembros no estáticos. Sin embargo, veo el siguiente ejemplo en el estándar C ++ 11 (12.6.2 / 12):

Los nombres en la lista de expresiones o en la lista inicial de braced de un inicializador de memoria se evalúan en el ámbito del constructor para el que se ha especificado el mem-initializer. [ Ejemplo:

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) { } };

Eso no será válido a menos que la evaluación de this->i se secuencia después de que i se inicializa.