正如我们所知,我们不能初始化switch
中任何一个case
中的变量,除非它是相应switch
的最后一个case
,因为变量的初始化确实需要在运行时执行定义(因为初始化器的值必须在该点确定),
但是
我们还知道,在编译过程中,constexpr
变量将被初始化,或者在代码中被替换为它的值。
因此,我尝试了以下代码,即初始化case 2
中的constexpr
变量Z
(这不是switch
的最后一个case
),但我得到一个错误,说明如下:
交叉“constexpr const int z”的初始化24|
常数表达式整数z{ 4 };//非法:如果存在后续案例,则不允许初始化
有人能解释一下这个错误背后的原因吗?
提前感谢您!
#include <iostream>
int main()
{
switch (1)
{
int y;
case 1:
y = 4;
break;
case 2:
constexpr int z{ 4 }; // ERROR
break;
case 3:
y=5;
break;
}
return 0;
}
2条答案
按热度按时间plupiseo1#
根据switch statement的c++参考
因为不允许控制转移进入变量的作用域,所以如果在语句内部遇到声明语句,则必须在其自己的复合语句中确定其作用域。
这意味着你实际上可以初始化一个局部变量,不管它是否在作用域内。例如,对你的代码做一个小的修改就可以编译:
检查它live on Coliru。
switch语句跳转到一个匹配的
case
,非常像goto statement
,然后,像goto语句一样,如果跳转到给定的行,你"跳过"变量的声明/初始化,会发生什么,这是不清楚的。请看下面的例子:
这是不能编译的,因为在执行跳转时,编译器不知道如何处理变量i。注意,如果没有跳转,就可以在
jump
标签后使用变量i
。但是如果只是"跳过"初始化,代码就会出现格式错误。switch语句本质上是一个goto,因此它有同样的限制。你声明的变量是constexpr
的事实并不改变这个限制。42fyovps2#
具有自动存储持续时间的变量的初始化发生在控制转移到它上面时,而不管它是否是
constexpr
变量。考虑以下代码(如果允许在
switch
的主体中初始化constexpr
变量):即使
z
是一个constexpr
变量,编译器仍然会把它放在堆栈上,把它的地址传递给f
,并且在运行时它在堆栈上的值会被赋值为4
。但是2
的情况怎么样呢?编译器在进入开关时会在堆栈上分配z
。但是逻辑上初始化器只有在它进入第一种情况时才“运行”。你不能在编译时“初始化”一个
constexpr
变量,因为它将被放置在堆栈中。是否将它完全删除并替换它的所有出现是一个优化(如果它的地址被获取,这并不总是可能的)。