И то, 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
просто означает, что значение не может быть изменено.