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.