constinit
说明符 (自 C++20 起)
来自 cppreference.com
内容 |
[编辑] 解释
constinit
说明符声明一个具有静态或线程 存储持续时间 的变量。如果一个变量用 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
[编辑] 说明
功能测试宏 | 值 | 标准 | 功能 |
---|---|---|---|
__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: init 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) |
指定变量或函数的值可以在编译时计算 |
常量表达式 | 定义可以在编译时计算的 表达式 |
常量初始化 | 将 静态 变量的初始值设置为编译时常量 |
零初始化 | 将对象的初始值设置为零 |