c++ - const vs constexpr en variables
c++11 (4)
¿Hay alguna diferencia entre las siguientes definiciones?
const double PI = 3.141592653589793;
constexpr double PI = 3.141592653589793;
Si no, ¿qué estilo se prefiere en C ++ 11?
A una constante simbólica constexpr se le debe dar un valor que se conoce en el momento de la compilación. Por ejemplo:
constexpr int max = 100;
void use(int n)
{
constexpr int c1 = max+7; // OK: c1 is 107
constexpr int c2 = n+7; // Error: we don’t know the value of c2
// ...
}
Para manejar los casos en que el valor de una "variable" que se inicializa con un valor que no se conoce en el momento de la compilación pero nunca cambia después de la inicialización, C ++ ofrece una segunda forma de constante (una constante ). Por ejemplo:
constexpr int max = 100;
void use(int n)
{
constexpr int c1 = max+7; // OK: c1 is 107
const int c2 = n+7; // OK, but don’t try to change the value of c2
// ...
c2 = 7; // error: c2 is a const
}
Estas "variables const " son muy comunes por dos razones:
- C ++ 98 no tenía constexpr, por lo que la gente usaba const .
- Los ítems de la lista "Variables" que no son expresiones constantes (su valor no se conoce en el momento de la compilación) pero que no cambian los valores después de la inicialización son en sí muy útiles.
Referencia: "Programación: principios y práctica usando C ++" por Stroustrup
Creo que hay una diferencia. Vamos a renombrarlos para que podamos hablar de ellos más fácilmente:
const double PI1 = 3.141592653589793;
constexpr double PI2 = 3.141592653589793;
Tanto PI1
como PI2
son constantes, lo que significa que no puede modificarlos. Sin embargo, solo PI2
es una constante de compilación. Se inicializará en tiempo de compilación. PI1
se puede inicializar en tiempo de compilación o tiempo de ejecución. Además, solo PI2
se puede utilizar en un contexto que requiere una constante de compilación. Por ejemplo:
constexpr double PI3 = PI1; // error
pero:
constexpr double PI3 = PI2; // ok
y:
static_assert(PI1 == 3.141592653589793, ""); // error
pero:
static_assert(PI2 == 3.141592653589793, ""); // ok
¿En cuanto a cuál deberías usar? Utilice lo que satisfaga sus necesidades. ¿Desea asegurarse de que tiene una constante de tiempo de compilación que se puede utilizar en contextos donde se requiere una constante de tiempo de compilación? ¿Desea poder inicializarlo con un cálculo realizado en tiempo de ejecución? Etc.
No hay diferencia aquí, pero importa cuando tienes un tipo que tiene un constructor.
struct S {
constexpr S(int);
};
const S s0(0);
constexpr S s1(1);
s0
es una constante, pero no promete ser inicializada en tiempo de compilación. s1
está marcado como constexpr
, por lo que es una constante y, como el constructor de S
también está marcado como constexpr
, se inicializará en tiempo de compilación.
Principalmente, esto es importante cuando la inicialización en el tiempo de ejecución llevaría mucho tiempo y usted querrá llevar ese trabajo al compilador, donde también consume mucho tiempo, pero no ralentiza el tiempo de ejecución del programa compilado.
constexpr indica un valor que es constante y conocido durante la compilación.
const indica un valor que solo es constante; No es obligatorio saberlo durante la compilación.
int sz;
constexpr auto arraySize1 = sz; // error! sz''s value unknown at compilation
std::array<int, sz> data1; // error! same problem
constexpr auto arraySize2 = 10; // fine, 10 is a compile-time constant
std::array<int, arraySize2> data2; // fine, arraySize2 is constexpr
Tenga en cuenta que const no ofrece la misma garantía que constexpr, ya que los objetos const no necesitan inicializarse con valores conocidos durante la compilación.
int sz;
const auto arraySize = sz; // fine, arraySize is const copy of sz
std::array<int, arraySize> data; // error! arraySize''s value unknown at compilation
Todos los objetos constexpr son const, pero no todos los objetos const son constexpr.
Si desea que los compiladores garanticen que una variable tiene un valor que se puede usar en contextos que requieren constantes de tiempo de compilación, la herramienta que debe buscar es constexpr, no const.