c++ - palabra - variables estaticas
¿La variable de constexto estática tiene sentido? (1)
Si tengo una variable dentro de una función (por ejemplo, una matriz grande), ¿tiene sentido declararla static
y constexpr
? constexpr
garantiza que la matriz se crea en tiempo de compilación, por lo que la static
sería inútil?
void f() {
static constexpr int x [] = {
// a few thousand elements
};
// do something with the array
}
¿La static
realmente está haciendo algo allí en términos de código o semántica generados?
La respuesta corta es que no solo es útil, sino que también es deseable.
En primer lugar, tenga en cuenta que static
y constexpr
son completamente independientes entre sí. static
define la duración del objeto durante la ejecución; constexpr
especifica que el objeto debería estar disponible durante la compilación. La compilación y la ejecución son disjuntas y no contiguas, tanto en tiempo como en espacio. Entonces, una vez que se compila el programa, constexpr
ya no es relevante.
Cada variable declarada constexpr
es implícitamente const
pero const
y static
son casi ortogonales (excepto por la interacción con enteros static const
).
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 los 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 una función con una matriz de const no-estática local, porque el compilador podría refugiarse en el principio de " as-if
", siempre que pueda demostrar que no hay otro objeto puede ser observado.
No será fácil probarlo, 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 las matrices, más o menos por definición, son direcciones. Por lo tanto, en la mayoría de los casos, la matriz const(expr)
no estática tendrá que volver a crearse en la pila en cada invocación, lo que frustra el punto de poder calcularla en tiempo de compilación.
Por otro lado, todos los observadores comparten un objeto static const
local y, además, pueden inicializarse incluso si nunca se llama a la función en la que está definida. Entonces, nada de lo anterior se aplica, y un compilador es libre no solo de generar solo una instancia de él; es gratis generar una sola instancia en almacenamiento de solo lectura.
Así que definitivamente deberías usar static constexpr
en tu ejemplo.
Sin embargo, hay un caso en el que no le conviene usar static constexper
. A menos que un objeto declarado por constexpr
sea utilizado por ODR o declarado static
, el compilador puede incluirlo de manera gratuita. Eso es bastante útil, ya que permite el uso de arreglos constexpr
temporales en tiempo de constexpr
sin contaminar el programa compilado con bytes innecesarios. En ese caso, es claro que no querrá usar static
, ya que es probable que la static
obligue al objeto a existir en tiempo de ejecución.