¿Hay algún beneficio para definir variables locales constantes como estáticas (c ++)?

9
void Animation::playAnimation() const
{
    static const int index = 0;
    const std::string& animationFileName = 
    m_animationContainer.getAnimationName(index);
    static const int zOrder = -1;
    static bool isLooping = false;

    AnimationBank::play(animationFileName,
                        zOrder,
                        isLooping);
}

¿Hay algún beneficio para definir variables locales constantes como static? O es innecesario e incluso una mala práctica.

TM
fuente
2
... también, por favor no publique en forma cruzada : stackoverflow.com/questions/44431574/… "La publicación cruzada está mal vista ya que conduce a respuestas fragmentadas en toda la red ..."
gnat
Pregunta editada.
TM

Respuestas:

10

Más allá de la muy buena respuesta de @ Christophe, el código generado para la estática es probablemente peor que el de la variable local, por lo que si está interesado en el beneficio oculto, las estadísticas son peores en los procesadores modernos.

La razón es que las estadísticas deben ubicarse en algún lugar de la memoria que puedan encontrar todos los otros subprocesos y todas las demás invocaciones. Esto básicamente significa ponerlos en la memoria global.

A lo largo de los años, los procesadores y compiladores juntos han optimizado significativamente el acceso a las variables locales debido a la popularidad de su uso, en comparación con otras variables, como los globales, las estadísticas y los campos. El compilador puede optar por almacenar una variable local en un registro de CPU, e incluso si no lo hace (por lo que utiliza la pila de invocación) toda la pila está casi seguramente en la memoria caché. Acceder a la pila suele ser un modo de direccionamiento de desplazamiento corto (fuera del registro del puntero de la pila). Sin embargo, el acceso a las variables globales o estáticas generalmente requiere un desplazamiento extendido o una dirección absoluta, por lo que las instrucciones resultantes son más largas que su equivalente para el acceso a la memoria de la pila.

Dicho todo esto, debido a la combinación de static y const, el compilador puede detectar que puede sustituir el valor constante en el punto de uso, por lo que quizás el uso de const mitiga lo anterior. Aún así, su fragmento muestra al menos una estadística no constante, por lo que tal vez la discusión sea de actualidad.

Erik Eidt
fuente
66
¿Estás seguro de que las constantes estáticas deben guardarse en la memoria?
MikeMB
5

No se trata de beneficios, sino de semántica:

  • Una variable estática en una función (incluso una función miembro) significa que la variable se comparte entre todas las llamadas de esa función. Entonces, una llamada de esa función tiene un efecto secundario en las llamadas posteriores.

  • Una variable no estática es exclusiva de cada ejecución de la función.

Entonces, a menos que sea necesario por alguna razón específica y bien justificada, mantenga las variables locales no estáticas.

Observación adicional: la variable estática también se comparte entre diferentes subprocesos. Por lo tanto, llamar a esta función desde más de un hilo a la vez puede dar lugar a condiciones de carrera y UB (incluso si se requieren diferentes objetos).

Christophe
fuente
44
A partir de C ++ 11, el estándar define las variables estáticas constantes a prueba de hilos. Las variables estáticas no constantes, por otro lado, no lo son.
Teimpz
55
Esto se trata de constantes. No pueden cambiar su valor, por lo que no existe una diferencia semántica significativa entre las constantes que se comparten entre las llamadas a múltiples funciones y las locales.
MikeMB
La única diferencia es si la inicialización tiene efectos secundarios.
MikeMB
1
@MikeMB De hecho, mi respuesta fue general. Si es un const, el optimizador lo propagará de todos modos, ya sea statico no. Pero todavía hay una sutil diferencia: como señaló, el inicializador de objetos podría usar algunos efectos secundarios, por lo que elegir estática o no podría distorsionar el comportamiento esperado. Por todas estas razones, aún sugeriría usarlo staticsi y solo si constes realmente algo que está intrínsecamente vinculado a la clase. Muestre la intención en el código y deje que el optimizador haga su trabajo.
Christophe
Entonces, semánticamente, no hace diferencia si la variable es una constante y no se toma su dirección. El resto de la pregunta es: ¿cuál debería usar?
user253751
1

Una variable local se inicializa o construye cada vez que se llama a la función. Las variables locales se almacenan en la pila y, por lo tanto, generalmente son seguras para subprocesos.

Una variable local estática se inicializa o construye solo una vez; la primera vez que se llama a la función Las variables estáticas locales no se almacenan en la pila y, por lo tanto, generalmente no son seguras para subprocesos.

Una variable local constante es una variable que no cambia y se inicializa o construye cada vez que se llama a la función. Las variables locales constantes se almacenan en la pila y, por lo tanto, generalmente son seguras para subprocesos.

Una variable local const estática es una variable que no cambia y se inicializa o construye solo una vez; la primera vez que se llama a la función Las variables const estáticas locales no se almacenan en la pila y, por lo tanto, generalmente no son seguras para subprocesos.

Los compiladores pueden optimizar las variables constantes en una constante de tiempo de compilación.

Los compiladores pueden optimizar las variables no estáticas manteniéndolas en registros en lugar de en la pila.

Theron W Genaux
fuente
¿Por qué las static constvariables locales no serían seguras para subprocesos? Su valor es constante incluso si su valor se encuentra en el hep.
sándwich de modelado unificado
@unifiedmodelingsandwich: ¿Qué sucede si dos hilos realizan la primera llamada a la función al mismo tiempo? Luego, ambos hilos tratarían de inicializar esa static constvariable.
Bart van Ingen Schenau
No en C ++ 11 no lo harían. La inicialización dinámica de la función estática local es segura para subprocesos.
Sebastian Redl
@BartvanIngenSchenau Desde C ++ 11, la inicialización de variables locales estáticas es segura para subprocesos . La A todavía es correcta al decir que, en general, no es seguro para subprocesos, pero sería más exacto decir que este es solo el caso antes de C ++ 11.
sándwich de modelado unificado
1
@unifiedmodelingsandwich: Gracias por la información. Estoy atascado en C ++ 03 :-(
Bart van Ingen Schenau