在我意识到语句需要保持不变之前,我想在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;
...
}
我宁愿使用if .. else:
if (myField == BAND_FIELD1(B)
variable1[B] = 123;
else if (myField == BAND_FIELD7(B)
variable7[B] = 321;
为什么C ++ switch语句仅限于常量表达式?
答案 0 :(得分:5)
C ++的一个优点是静态检查。 switch
语句是一个静态控制流构造,其功能在于能够(静态地)检查是否已经考虑了所有案例,并且能够合理地分组案例(例如,通过公共部分)。
如果要动态检查条件,可以使用各种技术(if
语句,条件运算符,关联数组,虚函数等)来完成这些操作。
答案 1 :(得分: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。
答案 2 :(得分:3)
当出现常量时,编译器可以为交换机生成最快的代码 - 例如。跳表或二叉搜索树。
当给定非常量值时,它不能生成比链式if
- else
语句更快的代码。无论如何你已经掌握了它!
答案 3 :(得分:3)
我的回答是C ++开关是C开关的剩余部分,它是PL / M等古老语言的遗留物。
在我看来,这个案例的唯一性只是一个可以追溯到70年代的构造的偶然副产品。
它并不保证所有案例都被覆盖,特别是考虑到C ++枚举的弱类型。
考虑到在场景后面经常生成的C ++汇编代码堆,认为C ++开关由于性能原因而限于常量,对我来说似乎有点丰富。
许多其他语言在switch语句中支持变量和/或非数字表达式,我没有看到很多程序员抱怨可能重复的案例值。
答案 4 :(得分: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。
答案 5 :(得分:0)
编译器在编译时分析常数值,以生成优化的查找表和决策树以快速选择案例。 例如,如果不能使用表,则编译器可能会使用3个cpu指令集生成高效的三叉决策树:与一个值进行比较以设置cpu标志,分支到其他情况下的分支,分支到其他情况下的分支或跌倒直到平等的情况。 请记住,C / C ++与性能有关。 也许将来会添加新的语法或扩展编译器,但是标准的进步试图是渐进的,并且不会破坏已经编写的代码,也不会使现有的编译器无效。