constexpr 变量

声明为 constexpr 的变量隐式为 const,其值可用作常量表达式。

#define 的比较

constexpr 是基于 #define 的编译时表达式的类型安全替代品。使用 constexpr,编译时计算的表达式将替换为结果。例如:

Version >= C++ 11

int main()
{
   constexpr int N = 10 + 2;
   cout << N;
}

将产生以下代码:

cout << 12;

基于预处理器的编译时宏将是不同的。考虑:

#define N 10 + 2

int main()
{
    cout << N;
}

将产生:

cout << 10 + 2;

这显然会转换为 cout << 10 + 2;。但是,编译器必须做更多的工作。此外,如果使用不正确,也会产生问题。

例如(使用 #define):

cout << N * 2;

形式:

cout << 10 + 2 * 2; // 14

但是预先评估的 constexpr 会正确地给出 24

const 的比较

const 变量是一个需要内存的变量。一个 constexpr 没有。constexpr 产生编译时常量,不能改变。你可能会说,const 也可能不会改变。但请考虑:

int main()
{
   const int size1 = 10;
   const int size2 = abs(10);

   int arr_one[size1]; 
   int arr_two[size2]; 
}

对于大多数编译器,第二个语句将失败(例如,可能与 GCC 一起使用)。你可能知道,任何数组的大小都必须是常量表达式(即导致编译时值)。第二个变量 size2 被分配了一些在运行时决定的值(即使你知道它是 10,对于编译器来说它不是编译时)。

这意味着 const 可能是也可能不是真正的编译时常量。你不能保证或强制执行特定的 const 值绝对是编译时。你可以使用 #define 但它有自己的陷阱。

因此,只需使用:

Version >= C++ 11

int main()
{
    constexpr int size = 10;

    int arr[size];
}

constexpr 表达式必须求值为编译时值。因此,你不能使用:

Version >= C++ 11

constexpr int size = abs(10);

除非函数(abs)本身返回一个 constexpr

所有基本类型都可以使用 constexpr 进行初始化。

Version >= C++ 11

constexpr bool FailFatal = true;
constexpr float PI = 3.14f;
constexpr char* site= "StackOverflow";

有趣的是,你也可以方便地使用 auto

Version >= C++ 11

constexpr auto domain = ".COM";  // const char * const domain = ".COM"
constexpr auto PI = 3.14;        // constexpr double