Ambos conste constexprpodem ser aplicados a variáveis e funções. Mesmo sendo semelhantes, na verdade são conceitos muito diferentes.
Ambos conste constexprsignificam 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 conste constexpré o momento em que seus valores de inicialização são conhecidos (avaliados). Embora os valores das constvariáveis possam ser avaliados no tempo de compilação e no tempo de execução, constexpreles 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 constvariáveis podem definir constantes de tempo de compilação como size1essas que podem ser usadas para especificar tamanhos de matriz e constantes de tempo de execução como size2essas 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 conste também constexprpodem ser aplicados a funções. Uma constfunção deve ser uma função membro (método, operador) em que a aplicação da constpalavra-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 constexprfunçõ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.
constexprcria uma constante em tempo de compilação;constsignifica simplesmente que o valor não pode ser alterado.