常量初始化
来自cppreference.com
设置静态变量的初值为编译时常量。
解释
如果静态或线程局部 (C++11 起)变量以常量被初始化(见下文),那么就会在其他所有初始化之前进行常量初始化以取代零初始化。
变量或临时对象 obj 在满足以下所有条件时会 以常量被初始化 :
- 要么它有初始化器,要么它的默认初始化会进行某些初始化,并且
- 它的初始化完整表达式是常量表达式,或者在 obj 是对象时,该完整表达式也可以为 obj 和它的子对象调用 constexpr 构造函数,即使这些对象不是字面类类型 (C++11 起)。
常量初始化的效果与其所对应的初始化的效果相同,但保证它在任何其他静态或线程局部 (C++11 起)对象的初始化前完成,并可能在编译时进行。
注解
编译器也可以对其他的静态及线程局部 (C++11 起)对象进行常量初始化,前提是它可以保证它们的值与遵循初始化的标准顺序时的结果相同。
实践中,常量初始化在编译时进行,并将预先计算的对象表示作为程序映像的一部分(如 .data
段)存储。如果变量既为 const
又被常量初始化,那么它的对象表示可存储于程序映像的只读段(如 .rodata
段)。
示例
运行此代码
#include <iostream> #include <array> struct S { static const int c; }; const int d = 10 * S::c; // 非常量表达式:此 S::c 前没有初始化器,此初始化在常量初始化之后发生 const int S::c = 5; // 常量初始化,保证首先发生 int main() { std::cout << "d = " << d << '\n'; std::array<int, S::c> a1; // OK:S::c 是常量表达式 // std::array<int, d> a2; // 错误:d 不是常量表达式 }
输出:
d = 50
缺陷报告
下列更改行为的缺陷报告追溯地应用于以前出版的 C++ 标准。
缺陷报告 | 应用于 | 出版时的行为 | 正确行为 |
---|---|---|---|
CWG 441 | C++98 | 不能常量初始化引用 | 使得可常量初始化 |
CWG 1489 | C++98 | 不明确对象的值初始化是否可以是常量初始化 | 可以是 |
CWG 1747 | C++98 | 绑定引用到函数不是常量初始化 | 可以是 |
CWG 1834 | C++11 | 绑定引用到亡值不是常量初始化 | 可以是 |
CWG 2026 | C++98 | 曾指定始终首先进行零初始化,甚至在常量初始化之前 | 适用常量初始化时不会进行零初始化 |
CWG 2366 | C++98 | 默认初始化不是常量初始化(需要常量初始化器) | 可以是 |