为什么C ++ switch语句限于常量表达式?

问题描述 投票:3回答:6

我想在switch语句中使用宏函数,然后才意识到该语句需要保持不变。示例(不编译):

#define BAND_FIELD1(B)   (10 * B + 1)
...
#define BAND_FIELD7(B)   (10 * B + 7)

int B = myField % 10;
switch (myField) {
    case BAND_FIELD1(B):
        variable1[B] = 123;
        break;
    case BAND_FIELD7(B):
        variable7[B] = 321;
        break;
    ...
}

我宁愿使用.. else:

if (myField == BAND_FIELD1(B)
    variable1[B] = 123;
else if (myField == BAND_FIELD7(B)
    variable7[B] = 321;

为什么C ++ switch语句限于常量表达式?

c++ switch-statement
6个回答
5
投票

C ++的优势之一就是它的静态检查。 switch语句是一个静态控制流构造,其作用在于能够(静态)检查是否已考虑所有案例,并且能够合理地对案例进行分组(例如,落入公共部分)。

如果要动态检查条件,您已经可以使用多种技术(if语句,条件运算符,关联数组,虚函数等等)进行检查。


5
投票

为什么c ++ switch语句限于常量表达式?

因为switch语句执行的检查是静态。这意味着需要在编译时知道这些表达式。

在C ++ 11中,您可以使用constexpr(如果表达式是由其他常量表达式派生的)。例如,考虑以下功能(代替您的#define):

inline constexpr int BAND_FIELD1(int B) {
    return 10 * B + 1;
}

用于以下简化的代码版本:

constexpr int myField = 0;
constexpr int B = myField % 10;

int variable1 = 0;
switch (myField) {
    case BAND_FIELD1(B):
        variable1 = 123;
        break;
    // ...
    default: break;
}

如您所见,上面的代码will easily compile


4
投票

当常量出现时,编译器可以为开关生成最快的代码,例如跳转表或二进制搜索树。

当给定非恒定值时,它无法生成比链式if-else语句快的代码。无论如何,您已经可以使用它!


3
投票

我的回答是,C ++开关是C开关的遗留物,而C开关是PL / M之类的古董语言的遗留物。

这种情况的独特性只是我认为可以追溯到70年代的结构的偶然机会。它不保证以任何方式都涵盖所有情况,尤其是考虑到C ++枚举的弱类型。

考虑到C ++通常在幕后产生的大量汇编代码,我认为出于性能原因C ++开关仅限于常量看来对我来说有点丰富。

[许多其他语言在switch语句中支持变量和/或非数字表达式,而且我还没有看到很多程序员抱怨可能的重复大小写值。


0
投票

为了帮助回答这个问题,请考虑以下内容(如果合法):

int a=15;
int b=16;
int c=15;
int value = a;

switch (value)
{
case a:
    // Value is A
    break;

case b:
    // value is B
    break;

case c:
    // value is C
    break;

default:
    // value is unknown
}

我们将永远不会执行C的代码,因为将改为执行A。切换的目的是检查具有唯一可测试值的值。它是一个干净的if..else if..else..if..else。


0
投票

编译器在编译时分析常数值,以生成优化的查找表和决策树以快速选择案例。例如,如果不能使用表,则编译器可以使用3个cpu指令集生成高效的三叉决策树:与一个值进行比较以设置cpu标志,分支到其他情况下的分支,分支到其他情况下的分支或跌倒直到平等的情况。请记住,C / C ++与性能有关。也许将来会添加新的语法或扩展编译器,但是标准的改进尝试是递增的,并且不会破坏已经编写的代码,也不会使现有的编译器无效。

© www.soinside.com 2019 - 2024. All rights reserved.