И то, constи другое constexprможно применять к переменным и функциям. Хотя они похожи друг на друга, на самом деле это очень разные понятия.
Оба constи constexprозначают, что их значения не могут быть изменены после их инициализации. Так, например:
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.
Принципиальным различием между constи constexprявляется время, когда их значения инициализации известны (оценены). Хотя значения constпеременных могут быть оценены как во время компиляции, так и во время выполнения, constexprвсегда оцениваются во время компиляции. Например:
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.
Основным преимуществом для того, чтобы знать, известно ли значение во время компиляции или во время выполнения, является тот факт, что константы времени компиляции могут использоваться всякий раз, когда необходимы константы времени компиляции. Например, C ++ не позволяет вам указывать C-массивы с переменной длиной.
int temp=rand(); // temp is generated by the the random generator at runtime.
int array1[10]; // OK.
int array2[temp]; // ERROR.
Итак, это означает, что:
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.
Таким образом, constпеременные могут определять как константы времени компиляции, подобные тем, size1которые можно использовать для указания размеров массива, так и константы времени выполнения, подобные size2тем, которые известны только во время выполнения и не могут использоваться для определения размеров массива. С другой стороны, constexprвсегда определяйте константы времени компиляции, которые могут указывать размеры массива.
И то, constи другое constexprможно применить и к функциям. constФункция должна быть функцией членом (метод, оператор) , где применением constключевого слова означает , что метод не может изменить значение их члена (не статический) полей. Например.
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.
}
};
А constexprэто другая концепция. Он отмечает функцию (член или не член) как функцию, которая может быть оценена во время компиляции, если в качестве аргументов переданы константы времени компиляции . Например, вы можете написать это.
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.
Кстати, constexprфункции - это обычные функции C ++, которые можно вызывать, даже если переданы непостоянные аргументы. Но в этом случае вы получаете значения не-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.
constexprТакже может быть применено к функциям членов (методы), операторов и даже конструкторов. Например.
class test2
{
static constexpr int function(int value)
{
return(value+1);
}
void f()
{
int x[function(10)];
}
};
Более «сумасшедший» образец.
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создает постоянную времени компиляции;constпросто означает, что значение не может быть изменено.