І те, 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 ++, які можна викликати, навіть якщо передаються непостійні аргументи. Але в цьому випадку ви отримуєте значення non-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
просто означає, що значення не можна змінити.