c++ - Matar números mágicos: “const int” vs “constexpr int”(o no hay diferencia al final)
magic-numbers (2)
Digamos que tengo un
magic number
que quiero deshacerme ...
//whatever.cpp
for (int i = 0; i < 42; i++)
{
//...
}
Razonablemente podría matarlo de dos maneras:
O bien con
const int SOMETHING_SOMETHING_MEANING_OF_LIFE = 42
o con
constexpr int SOMETHING_SOMETHING_MEANING_OF_LIFE = 42
en el archivo fuente
.cpp
.
¿Hay alguna diferencia significativa entre los dos en este caso (recuerdo que el compilador dedujo que, en cualquier caso, que el valor no cambia y, por lo tanto, el
42
está realmente codificado en el bucle resultante / bucle desenrollado / cualquier código de máquina) o ¿Se reduce a gusto personal?
En un tema relacionado: ¿qué pasaría si el
magic number
(y, por lo tanto, la cosa que lo reemplaza) se declarara en un archivo de encabezado (
.h
) en lugar de un archivo de origen (
.ccp
)?
.ccp
cambiaría las cosas (y si es así, cómo) ?
¿Hay alguna diferencia significativa entre los dos en este caso (recuerdo que la compilación dedujo que, en cualquier caso, el valor no cambia y en realidad codifica el 42 en el bucle resultante / el bucle desenrollado / cualquier otro código) o se reduce a ¿gusto personal?
No habrá ninguna diferencia en el código en el caso que ha mostrado.
Sin embargo, la diferencia es que una variable
constexpr
garantiza que el valor se conoce en tiempo de compilación.
Ver la respuesta de @ VittorioRomeo.
También es bueno escribir
constexpr
si es realmente un valor de tiempo de compilación, para fines de documentación: cuando alguien lee su código y ve
constexpr
, automáticamente sabe que es un valor verdaderamente fijo.
Esto es importante en el caso de que la inicialización no sea trivial (por ejemplo, una llamada a una función).
También puede ver
constexpr
variables
constexpr
como el verdadero reemplazo de las macros C que contenían literales (por ejemplo,
#define FOO 123
).
Finalmente, recuerda que
constexpr
implica
const
.
En un tema relacionado: ¿qué pasaría si el número mágico (y la cosa que lo reemplaza) se declarara en un archivo de encabezado en lugar de un archivo .ccp? ¿Eso cambiaría las cosas?
No. Sin embargo, si está declarando variables globales en un archivo de encabezado, es probable que desee usar
inline
(disponible en C ++ 17) sobre
constexpr
, de modo que solo tenga una entidad en el programa, lo que es una ventaja. para evitar problemas de ODR y posiblemente ahorrar memoria y tiempo de inicialización.
Consulte ¿Deben las variables `const` y` constexpr` en los encabezados estar `en línea ''para evitar violaciones de ODR? para más información.
const int
puede usarse como parte de una
expresión constante
solo si se inicializó desde una, pero no le da la garantía de que lo fue.
const int i = 42; // OK, usable in a constant expression
int j = 42;
const int k = j; // OK, not usable in a constant expression
constexpr int
garantiza que el inicializador de su variable es una
expresión constante
, de lo contrario su programa no se compilará.
constexpr int i = 42; // OK, usable in a constant expression
int j = 42;
constexpr int k = j; // Compile-time error, ''j'' is not a constant expression
Por lo tanto, si desea asegurarse de que su inicializador sea realmente una
expresión constante
,
constexpr
es una mejor opción.