Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/158.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 为什么在另一个案例的块中允许case语句?_C++_Switch Statement - Fatal编程技术网

C++ 为什么在另一个案例的块中允许case语句?

C++ 为什么在另一个案例的块中允许case语句?,c++,switch-statement,C++,Switch Statement,我遇到过如下代码: switch(i) { case 2: { std::cout << "2"; break; case 3: std::cout << "3"; break; } case 4: { std::cout << "4"; break; } } 开关(一){ 案例2:{ C/C++中的std::coutswitch语

我遇到过如下代码:

  switch(i) {
    case 2: {
      std::cout << "2";
      break;
    case 3:
      std::cout << "3";
      break;
    }
    case 4: {
      std::cout << "4";
      break;
    }    
  }
开关(一){
案例2:{

C/C++中的std::cout
switch
语句是一种美化的
goto
语句(具有一些优化优势)


因此,您可以使用
case
标签,就像使用
goto
标签一样。特别是,只要您不绕过任何变量初始化,就可以在块内跳转。

您可以但不应该在
开关中滥用case标签
比这更糟糕,也比.Duff's d更糟糕evice有着令人怀疑的特权,几乎似乎有用,但却可以被视为滥用
开关

<> P>不是所有的滥用代码>开关可以声称是有用的。例如,这编译为C或C++,即使有严格的警告设置:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main(int argc, char **argv)
{
    unsigned seed;
    if (argc == 2)
        seed = atoi(argv[1]);
    else
        seed = time(0);
    printf("seed: %u\n", seed);
    srand(seed);

    int i = rand() % 10;
    int j = 21;
    int k = 37;
    printf("i: %d\n", i);
    switch (i)
    {
    case 1:
        for (j = 10; j > i; j--)
        {
        case 2:
            printf("case 2:\n");
            for (k = j - 1; k > 0; k--)
            {
            case 6:
                printf("case 6:\n");
            default:
                printf("%d-%d-%d\n", i, j, k);
            }
        case 5:
            printf("case 5:\n");
            printf("%d-%d\n", i, j);
            break;
        }
        break;
    case 3:
        printf("case 3:\n");
        break;
    }
    return 0;
}
#包括
#包括
#包括
int main(int argc,字符**argv)
{
无标记种子;
如果(argc==2)
seed=atoi(argv[1]);
其他的
种子=时间(0);
printf(“种子:%u\n”,种子);
srand(种子);
int i=rand()%10;
int j=21;
int k=37;
printf(“i:%d\n”,i);
开关(一)
{
案例1:
对于(j=10;j>i;j--)
{
案例2:
printf(“案例2:\n”);
对于(k=j-1;k>0;k--)
{
案例6:
printf(“案例6:\n”);
违约:
printf(“%d-%d-%d\n”,i,j,k);
}
案例5:
printf(“案例5:\n”);
printf(“%d-%d\n”,i,j);
打破
}
打破
案例3:
printf(“案例3:\n”);
打破
}
返回0;
}
参数处理允许您设置种子,以便您可以根据需要复制结果。我不认为它有用;事实上,它没有用处。请注意,循环内部的
break
会中断循环,而不是
开关


基本上,
大小写
标签(和
默认值
)必须在
开关
的范围内,并且与最里面的
开关
相关联。它们几乎没有其他约束。必须小心不要跳过变量初始化等(这就是为什么
j
k
是在
开关()之外定义的。)但是,否则,它们只是标签,控件将在适当的时候流向它们。代码>开关> /Cuth>在C和C++中的语句并不像您所想的那样逻辑。请参阅极端例子。@ NeilButterworth,这是一个深远的声明,我不能同意。@ NeilButterworth,当使用合理时,提供良好的阅读。能力(与一长串的
if…else if…
语句相比)在某些情况下提供了优化的好处。前者的好处大于后者。@NeilButterworth实际上,没有“魔力”相信
开关
块平均生成更快的代码,只是简单的逻辑。
开关
块执行一次检查和一次或两次跳转(跳转到
案例
,在
中断时跳出
(如果存在)),而未优化的
if..else if..else
链执行一次检查和跳转(到
else
,或到链的末端)每执行
if
(这意味着对于
if..else if..else if..else
块,它执行1-3次检查和跳转)。对于任何可以写为其中一个的块,
开关
平均效率会稍高一些。开关块强烈提示优化编译器应该将其优化为跳转表。一系列if语句强烈提示它不应该。我见过编译器将转换一系列If语句转换为跳转表,@Justin,但绝大多数情况下,它不会。假设您将写出您的意思。如果一系列If语句的大小写超过可读范围,则您将其作为开关大小写,并应将其编译为跳转表。否则,跳转表的开销为每性能损失。