Namespaces
Variants

constinit specifier (since C++20)

From cppreference.net
C++ language
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
constexpr (C++11)
consteval (C++20)
constinit (C++20)
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

关键词

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) 指定变量或函数的值可在编译时计算
常量表达式 定义可在编译时求值的 表达式
常量初始化 静态 变量的初始值设为编译时常量
零初始化 将对象的初始值设为零