constinit
说明符 (C++20 起)
来自 cppreference.cn
目录 |
[编辑] 解释
constinit
说明符声明一个具有静态或线程存储期的变量。
|
(C++26 起) |
如果变量使用 constinit
声明,则其初始化声明必须使用 constinit
。 如果使用 constinit
声明的变量具有动态初始化(即使它作为静态初始化执行),则程序是非良构的。
如果在初始化声明点没有可达的 constinit
声明,则程序是非良构的,无需诊断。
constinit
不能与 constexpr
一起使用。 当声明的变量是引用时,constinit
等价于 constexpr
。 当声明的变量是对象时,constexpr
要求对象必须具有静态初始化和常量析构,并使对象具有 const 限定,但是,constinit
不要求常量析构和 const 限定。 因此,具有 constexpr 构造函数但没有 constexpr 析构函数的类型对象(例如 std::shared_ptr<T>
)可以用 constinit
声明,但不能用 constexpr
声明。
const char* g() { return "dynamic initialization"; } constexpr const char* f(bool p) { return p ? "constant initializer" : g(); } constinit const char* c = f(true); // OK // constinit const char* d = f(false); // error
constinit
也可以在非初始化声明中使用,以告知编译器 thread_local
变量已初始化,从而减少隐藏的保护变量可能产生的开销。
extern thread_local constinit int x; int f() { return x; } // no check of a guard variable needed
[编辑] 备注
特性测试宏 | 值 | Std | 特性 |
---|---|---|---|
__cpp_constinit |
201907L |
(C++20) | constinit
|
[编辑] 关键字
[编辑] 示例
运行此代码
#include <cassert> constexpr int square(int i) { return i * i; } int twice(int i) { return i + i; } constinit int sq = square(2); // OK: initialization is done at compile time // constinit int x_x = twice(2); // Error: compile time initializer required int square_4_gen() { static constinit int pow = square(4); // constinit int prev = pow; // Error: constinit can only be applied to a // variable with static or thread storage duration int prev = pow; pow = pow * pow; return prev; } int main() { assert(sq == 4); sq = twice(1); // Unlike constexpr this value can be changed later at runtime assert(sq == 2); assert(square_4_gen() == 16); assert(square_4_gen() == 256); assert(square_4_gen() == 65536); }
[编辑] 缺陷报告
以下行为变更缺陷报告已追溯应用于先前发布的 C++ 标准。
DR | 应用于 | 已发布行为 | 正确行为 |
---|---|---|---|
CWG 2543 | C++20 | 如果使用 constinit 声明的变量,则行为不明确作为静态初始化的一部分进行动态初始化 |
程序是非- 良构的 |
[编辑] 参见
consteval 说明符(C++20) |
指定函数为立即函数,即,对函数的每次调用都必须在常量求值中 |
constexpr 说明符(C++11) |
指定变量或函数的值可以在编译时计算 |
常量表达式 | 定义一个可以在编译时求值的表达式 |
常量初始化 | 将静态变量的初始值设置为编译时常量 |
零初始化 | 将对象的初始值设置为零 |