constinit
specifier
(since C++20)
| General topics | ||||||||||||||||
| Flow control | ||||||||||||||||
| Conditional execution statements | ||||||||||||||||
| Iteration statements (loops) | ||||||||||||||||
|
||||||||||||||||
| Jump statements | ||||||||||||||||
| Functions | ||||||||||||||||
| Function declaration | ||||||||||||||||
| Lambda function expression | ||||||||||||||||
inline
specifier
|
||||||||||||||||
| Dynamic exception specifications ( until C++17* ) | ||||||||||||||||
noexcept
specifier
(C++11)
|
||||||||||||||||
| Exceptions | ||||||||||||||||
| Namespaces | ||||||||||||||||
| Types | ||||||||||||||||
| Specifiers | ||||||||||||||||
|
||||||||||||||||
| Storage duration specifiers | ||||||||||||||||
| Initialization | ||||||||||||||||
| Expressions | ||||||||||||||||
| Alternative representations | ||||||||||||||||
| Literals | ||||||||||||||||
| Boolean - Integer - Floating-point | ||||||||||||||||
| Character - String - nullptr (C++11) | ||||||||||||||||
| User-defined (C++11) | ||||||||||||||||
| Utilities | ||||||||||||||||
| Attributes (C++11) | ||||||||||||||||
| Types | ||||||||||||||||
typedef
declaration
|
||||||||||||||||
| Type alias declaration (C++11) | ||||||||||||||||
| Casts | ||||||||||||||||
| Memory allocation | ||||||||||||||||
| Classes | ||||||||||||||||
| Class-specific function properties | ||||||||||||||||
|
||||||||||||||||
| Special member functions | ||||||||||||||||
|
||||||||||||||||
| Templates | ||||||||||||||||
| Miscellaneous | ||||||||||||||||
|
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
目录 |
说明
constinit 说明符声明具有静态或线程 存储期 的变量。
|
constinit 说明符也可应用于 结构化绑定 声明。在此情况下, constinit 同样会作用于该声明引入的 唯一命名变量 。 |
(since 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); // 正确 // constinit const char* d = f(false); // 错误
constinit 也可用于非初始化声明,以告知编译器某个 thread_local 变量已完成初始化, 从而减少 原本因隐藏的守卫变量而产生的开销。
extern thread_local constinit int x; int f() { return x; } // 无需检查防护变量
注释
| 功能测试宏 | 值 | 标准 | 功能 |
|---|---|---|---|
__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); // 正确:初始化在编译时完成 // constinit int x_x = twice(2); // 错误:需要编译时初始化器 int square_4_gen() { static constinit int pow = square(4); // constinit int prev = pow; // 错误:constinit 只能应用于 // 具有静态或线程存储期的变量 int prev = pow; pow = pow * pow; return prev; } int main() { assert(sq == 4); sq = twice(1); // 与 constexpr 不同,此值可在运行时后续更改 assert(sq == 2); assert(square_4_gen() == 16); assert(square_4_gen() == 256); assert(square_4_gen() == 65536); }
缺陷报告
以下行为变更缺陷报告被追溯应用于先前发布的C++标准。
| 缺陷报告 | 应用于 | 发布时的行为 | 正确行为 |
|---|---|---|---|
| CWG 2543 | C++20 |
若使用
constinit
声明的变量
在静态初始化阶段进行动态初始化,其行为不明确 |
此情况下程序
格式错误 |
参见
consteval
说明符
(C++20)
|
指定函数为 立即函数 ,即每次对该函数的调用都必须在常量求值中执行 |
constexpr
说明符
(C++11)
|
指定变量或函数的值可在编译时计算 |
| 常量表达式 | 定义可在编译时求值的 表达式 |
| 常量初始化 | 将 静态 变量的初始值设为编译时常量 |
| 零初始化 | 将对象的初始值设为零 |