¿Tiene sentido la variable estática constexpr?


Si tengo una variable dentro de una función (digamos, una matriz grande), ¿tiene sentido declararla tanto static como constexpr? constexpr garantiza que la matriz se crea en tiempo de compilación, por lo que el static sería inútil?

void f() {
    static constexpr int x [] = {
        // a few thousand elements
    };
    // do something with the array
}

Es el static realmente haciendo algo allí en términos de código generado o semántica?

Author: David Stone, 2012-12-13

1 answers

La respuesta corta es que no solo es static útil, es bastante bien siempre va a ser deseado.

Primero, note que static y constexpr son completamente independientes el uno del otro. static define el tiempo de vida del objeto durante la ejecución; constexpr especifica que el objeto debe estar disponible durante la compilación. La compilación y ejecución son disjuntos y discontiguos, tanto en el tiempo como en el espacio. Así que una vez compilado el programa, constexpr ya no es relevante.

Cada variable declarado constexpr es implícitamente const pero const y static son casi ortogonales (excepto por la interacción con static const enteros.)

El modelo de objetos C++ (§1.9) requiere que todos los objetos que no sean campos de bits ocupen al menos un byte de memoria y tengan direcciones; además, todos estos objetos observables en un programa en un momento dado deben tener direcciones distintas (párrafo 6). Esto no requiere que el compilador cree una nueva matriz en la pila para cada invocación de un función con un array const local no estático, porque el compilador podría refugiarse en el principio as-if siempre que pueda probar que no se puede observar ningún otro objeto similar.

Eso no va a ser fácil de probar, desafortunadamente, a menos que la función sea trivial (por ejemplo, no llama a ninguna otra función cuyo cuerpo no sea visible dentro de la unidad de traducción) porque los arrays, más o menos por definición, son direcciones. Así que en la mayoría de los casos, la matriz no estática const(expr) tendrá que ser recreado en la pila en cada invocación, lo que frustra el punto de ser capaz de calcularlo en tiempo de compilación.

Por otro lado, un objeto local static const es compartido por todos los observadores, y además puede ser inicializado incluso si la función en la que está definido nunca es llamada. Así que nada de lo anterior se aplica, y un compilador no solo es libre de generar una sola instancia de él; es libre de generar una sola instancia de él en el almacenamiento de solo lectura.

Así que definitivamente deberías use static constexpr en su ejemplo.

Sin embargo, hay un caso en el que no querrías usar static constexpr. A menos que un objeto constexpr declarado sea ODR-used o declarado static, el compilador es libre de no incluirlo en absoluto. Eso es bastante útil, porque permite el uso de arreglos temporales en tiempo de compilación constexpr sin contaminar el programa compilado con bytes innecesarios. En ese caso, claramente no querrá usar static, ya que static es probable que obligue al objeto a existir en ejecución.

 148
Author: rici,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-09-08 11:36:59