命名空间
变体
操作

constinit 说明符 (C++20 起)

来自 cppreference.cn
< cpp‎ | language
 
 
C++ 语言
 
 

目录

[编辑] 解释

constinit 说明符声明一个具有静态或线程存储期的变量。

constinit 说明符也可以应用于结构化绑定声明。在这种情况下,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

[编辑] 关键字

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