Descubrí que hay un orden de ejecución diferente entre dos declaraciones similares (la única diferencia es que la de abajo tiene un ; adicional). El orden de los destructores es diferente. ¿C ++ tiene una especificación correspondiente sobre eso o es solo un comportamiento no especificado?

Entorno: GCC10

#include <iostream>

template <int num>
struct S {
  S() {std::cout << "S(" << num << ")\n"; }
  ~S() {std::cout << "~S(" << num << ")\n"; }
};

int main() {
  ({S<1>(), S<2>();});
  std::cout << "-----------------------------------\n";
  ({S<3>(), S<4>();;});
}

Salida:

S(1)
S(2)
~S(1)
~S(2)
-----------------------------------
S(3)
S(4)
~S(4)
~S(3)
2
eddie kuo 26 oct. 2020 a las 05:52

1 respuesta

La mejor respuesta

Esto no es C ++ estándar. Esta es una extensión de GCC conocida como expresión de declaración. Una declaración compuesta entre paréntesis puede aparecer donde se permite una expresión. Si la última declaración en el bloque entre llaves es una declaración de expresión, entonces el valor de esta expresión también es el valor de la expresión de la declaración general; de lo contrario, la expresión de instrucción es de tipo void y no tiene valor.

Tu primer ejemplo es aproximadamente equivalente a

([](){ return S<1>(), S<2>(); })();

(esa es una lambda que se crea y luego se llama inmediatamente). Hay una expresión de coma que crea S<1> y S<2> temporales. S<1> se destruye, S<2> se copia, técnicamente, al valor de retorno, pero esa copia se elide. Si no fuera por esta elisión de copia, verías

S<1>()
S<2>()
S<2>(S<2>&&)  // (1) move constructor
~S<2>()  // (2) the original temporary is destroyed
~S<1>()
~S<2>()  // the copy is destroyed outside of the lambda

Pero el par (1) / (2) se elimina, dejando la secuencia que observa en su ejemplo.

En el segundo ejemplo, la última declaración entre llaves no es una expresión, por lo que el conjunto tampoco tiene valor. Es aproximadamente equivalente a

([](){ S<3>(), S<4>(); return; })();

Ambos temporales se crean y destruyen dentro de la lambda, y se aplican las reglas habituales: los temporales se destruyen en el orden inverso de construcción.

6
Igor Tandetnik 26 oct. 2020 a las 03:31