Ambos const
e constexpr
podem ser aplicados a variáveis e funções. Mesmo sendo semelhantes, na verdade são conceitos muito diferentes.
Ambos const
e constexpr
significam que seus valores não podem ser alterados após a inicialização. Então, por exemplo:
const int x1=10;
constexpr int x2=10;
x1=20; // ERROR. Variable 'x1' can't be changed.
x2=20; // ERROR. Variable 'x2' can't be changed.
A principal diferença entre const
e constexpr
é o momento em que seus valores de inicialização são conhecidos (avaliados). Embora os valores das const
variáveis possam ser avaliados no tempo de compilação e no tempo de execução, constexpr
eles sempre são avaliados no tempo de compilação. Por exemplo:
int temp=rand(); // temp is generated by the the random generator at runtime.
const int x1=10; // OK - known at compile time.
const int x2=temp; // OK - known only at runtime.
constexpr int x3=10; // OK - known at compile time.
constexpr int x4=temp; // ERROR. Compiler can't figure out the value of 'temp' variable at compile time so `constexpr` can't be applied here.
A principal vantagem de saber se o valor é conhecido em tempo de compilação ou tempo de execução é o fato de que constantes de tempo de compilação podem ser usadas sempre que são necessárias constantes de tempo de compilação. Por exemplo, o C ++ não permite especificar matrizes C com os comprimentos variáveis.
int temp=rand(); // temp is generated by the the random generator at runtime.
int array1[10]; // OK.
int array2[temp]; // ERROR.
Então isso significa que:
const int size1=10; // OK - value known at compile time.
const int size2=temp; // OK - value known only at runtime.
constexpr int size3=10; // OK - value known at compile time.
int array3[size1]; // OK - size is known at compile time.
int array4[size2]; // ERROR - size is known only at runtime time.
int array5[size3]; // OK - size is known at compile time.
Portanto, as const
variáveis podem definir constantes de tempo de compilação como size1
essas que podem ser usadas para especificar tamanhos de matriz e constantes de tempo de execução como size2
essas conhecidas apenas em tempo de execução e não podem ser usadas para definir tamanhos de matriz. Por outro ladoconstexpr
defina sempre constantes de tempo de compilação que podem especificar tamanhos de matriz.
Ambos const
e também constexpr
podem ser aplicados a funções. Uma const
função deve ser uma função membro (método, operador) em que a aplicação da const
palavra-chave significa que o método não pode alterar os valores de seus campos membros (não estáticos). Por exemplo.
class test
{
int x;
void function1()
{
x=100; // OK.
}
void function2() const
{
x=100; // ERROR. The const methods can't change the values of object fields.
}
};
A constexpr
é um conceito diferente. Ele marca uma função (membro ou não membro) como a função que pode ser avaliada em tempo de compilação se constantes de tempo de compilação forem passadas como argumentos . Por exemplo, você pode escrever isso.
constexpr int func_constexpr(int X, int Y)
{
return(X*Y);
}
int func(int X, int Y)
{
return(X*Y);
}
int array1[func_constexpr(10,20)]; // OK - func_constexpr() can be evaluated at compile time.
int array2[func(10,20)]; // ERROR - func() is not a constexpr function.
int array3[func_constexpr(10,rand())]; // ERROR - even though func_constexpr() is the 'constexpr' function, the expression 'constexpr(10,rand())' can't be evaluated at compile time.
A propósito, as constexpr
funções são as funções regulares do C ++ que podem ser chamadas mesmo que argumentos não constantes sejam passados. Mas, nesse caso, você está obtendo os valores não constexpr.
int value1=func_constexpr(10,rand()); // OK. value1 is non-constexpr value that is evaluated in runtime.
constexpr int value2=func_constexpr(10,rand()); // ERROR. value2 is constexpr and the expression func_constexpr(10,rand()) can't be evaluated at compile time.
o constexpr
pode ser aplicado às funções membro (métodos), operadores e até construtores. Por exemplo.
class test2
{
static constexpr int function(int value)
{
return(value+1);
}
void f()
{
int x[function(10)];
}
};
Uma amostra mais 'louca'.
class test3
{
public:
int value;
// constexpr const method - can't chanage the values of object fields and can be evaluated at compile time.
constexpr int getvalue() const
{
return(value);
}
constexpr test3(int Value)
: value(Value)
{
}
};
constexpr test3 x(100); // OK. Constructor is constexpr.
int array[x.getvalue()]; // OK. x.getvalue() is constexpr and can be evaluated at compile time.
constexpr
cria uma constante em tempo de compilação;const
significa simplesmente que o valor não pode ser alterado.