constexpr,constinit 和 consteval
C++11 中增加了关键字 constexpr
,C++20 中增加了关键字 constinit
和 consteval
。其中 constexpr
用于声明常量表达式,consteval
确保常量求值,constinit
用于静态初始化。
constexpr
constexpr
用于声明常量表达式:一个函数或者一个变量如果是 constexpr
的,那么代表其可以用于常量求值语境(在编译期进行计算)。例如用于模板参数或者数组下标。
声明为 constexpr
的函数也可以非常量使用,constexpr
声明只代表其具有常量求值的可能性。
如果想真正做到常量求值,需要保证所有值都是经由常量表达式计算而来的。
C++ Reference 上对函数何时能声明为 constexpr
有详细的描述:constexpr。
consteval
由于 constexpr
函数可用于非常量使用,此时编译器可能会忽略 constexpr
修饰,产生一个运行期函数调用,而 consteval
修饰的函数则一定确保被常量使用,从而使得调用点一定获得一个常量,保证没有运行时函数调用。
constinit
constinit
说明符声明拥有静态或线程存储期的变量。若变量以 constinit
声明,则其初始化声明必须应用 constinit
。
实际上这就是强制一个静态储存期的变量必须被静态初始化,而不是在其他地方进行动态初始化,使得其在声明位置一定得到初始化。
constexpr
强制对象必须拥有静态初始化和常量析构,并使对象有 const
限定,然而 constinit
不强制常量析构和 const
限定。结果是拥有 constexpr
构造函数且无 constexpr
析构函数的类型(例如 std::shared_ptr<T>
)的对象可能可以用 constinit
,但不能用 constexpr
声明。