看这个小例子:
constinit int a = 0;
constexpr int b = a;
Run Code Online (Sandbox Code Playgroud)
clang不会编译它(godbolt):
2:15:错误:constexpr变量“ b”必须由常量表达式初始化
这是正确的诊断程序吗?
如果是,标准为何不允许这样做?我了解,该a值可能会在运行期间(甚至在动态初始化期间)发生变化,但是在常量初始化时,其值是已知的,因此可以将其用于初始化b。
是的,诊断是正确的。constexpr变量必须用常量表达式初始化,并且a不是常量表达式(它是可变变量)。
constinit( P1143 )的目的是,如果变量的初始化不是常量,则强制变量声明格式错误。它不会改变变量本身的任何内容,比如它的类型或任何东西(以constexpr隐式的方式const)。愚蠢的例子:
struct T {\n int i;\n constexpr T(int i) : i(i) { }\n T(char c) : i(c) { }\n};\n\nconstinit T c(42); // ok\nconstinit T d(\'X\'); // ill-formed\nRun Code Online (Sandbox Code Playgroud)\n\n这就是全部constinit,唯一真正的规则是[dcl.constinit]/2:
\n\n\n如果用说明符声明的变量
\nconstinit具有动态初始化 ([basic.start.dynamic]),则程序格式错误。\n [注意:constinit说明符确保变量在静态初始化期间初始化 ([basic.start.static] ]).\n \xe2\x80\x94尾注\n ]
const inconstinit仅指初始化,不是变量,也不是任何类型。请注意,它也不会更改执行的初始化类型,它只是诊断是否执行了错误的类型。
在:
\n\nconstinit int a = 0;\nconstexpr int b = a;\nRun Code Online (Sandbox Code Playgroud)\n\n0是一个常量表达式,因此 的初始化a是格式良好的。一旦我们超越了这一点,说明符就不会做任何事情。它相当于:
int a = 0; // same behavior, a undergoes constant initialization\nconstexpr int b = a;\nRun Code Online (Sandbox Code Playgroud)\n\n这显然是不正确的。
\n\n\n\n\n但在常量初始化时,它的值是已知的,因此可以用它来初始化
\nb。
当然,此时此刻。关于什么:
\n\nconstinit int a = 0;\ncin >> a;\nconstexpr int b = a;\nRun Code Online (Sandbox Code Playgroud)\n\n这显然是飞不起来的。允许这一点需要扩展常量表达式(在我看来,这已经是标准中最复杂的规则)以允许非常量变量,但只能在初始化后立即使用?复杂性似乎不值得,因为你总是可以写:
\n\nconstexpr int initializer = 0;\nconstinit int a = initializer;\nconstexpr int b = initializer;\nRun Code Online (Sandbox Code Playgroud)\n
| 归档时间: |
|
| 查看次数: |
120 次 |
| 最近记录: |