常量
constexpr
constexpr声明了一个可以在编译时求值的常量表达式,用于变量、函数和构造函数。
I.constexpr关键字声明的变量必须在编译时就能得到一个常量的值。
II.constexpr指示函数可以在编译时进行求值。这样的函数只能包含可以在编译时求值的表达式,并且它们的参数和返回值类型必须是字面类型。字面类型是指在编译期间可以被完全求值的类型,包括算术类型、指针类型、枚举类型以及由这些类型组成的数组、结构体和联合体。调用constexpr函数时,如果参数是常量表达式,结果也将在编译时求值。
Case :

III.constexpr可以用于声明构造函数,使得对象可以在编译时进行构造。
Case :

使用constexpr可以在编译时进行更多的计算,从而提升性能和灵活性。然而,constexpr有一些限制,如不能包含非常量表达式的语句、不能使用动态内存分配等。
扩展
C++20开始,在constexpr上下文中可以使用std::string和std::vector。
Case 1 :

Case 2 :

C++20开始,std::string和std::vecotr具有限定的构造函数和析构函数,这是可在编译时使用的前提。所以,分配给string或vector对象的内存,也必须在编译时释放。如果试图在运行时使用constexpr函数返回的vector或string对象,会得到在常量求值期间分配内存的错误。因为在编译期间分配并释放了vector和string对象,所以它们在运行时不可用。如需在运行时使用它们,可以考虑用array或内置数组替换vector,用字符数组或string_view替换string。
此外,在运行时仍然可以使用vector和string对象的适配constexpr的方法,比如size。

constexpr和宏
I.constexpr是在编译时求值的机制,它在编译期间计算常量的值,并在运行时使用该值。而宏是在预处理阶段进行简单的文本替换。
II.constexpr在编译时对常量进行类型检查,确保常量的类型是正确的。它保留了C++的类型系统,并提供了更好的类型安全性。而宏没有类型信息,无法进行类型检查,可能导致潜在的类型错误。
III.宏在预处理阶段进行简单的文本替换,这意味着它允许符号重定义。如果在多个地方使用相同的宏定义,后面的定义将覆盖前面的定义。这可能导致不可预测的行为。而constexpr具有唯一定义,不会出现符号重定义的问题。
简而言之,一般使用constexpr定义常量,而将宏定义主要用于其他的预处理任务。