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