switch case的消除

dhc_6huoCangLong 2010-04-06 02:47:56
请问为什么要消除switch case呢

原本有段代码:
switch(cmd)
{
case cmd1:
printf("xx1");
break;
case cmd2:
printf("xx2");
break;
case cmd3:
printf("xx3");
break;
default:
break;
}

现在我把这段代码改为:
char* msgArray[cmdMax];
msgArray[cmd1] = "xx1";
msgArray[cmd2] = "xx2";
msgArray[cmd3] = "xx3";

printf(msgArray[cmd]);

效率会提高吗
...全文
535 40 打赏 收藏 转发到动态 举报
写回复
用AI写文章
40 条回复
切换为时间正序
请发表友善的回复…
发表回复
na2650945 2010-04-08
  • 打赏
  • 举报
回复
[Quote=引用 26 楼 haosuai 的回复:]
下面是个比较的代码

C/C++ code

int li_tmp = 1;
switch(li_tmp)
{
case 1:
printf("11");
break;
case 2:
printf("22");
break;
case 3:
……
[/Quote]
学习啦。
na2650945 2010-04-08
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 dhc_6huocanglong 的回复:]
我又试了函数指针和map
至于map的话 和我第一种数组有什么区别吗?
map能提高效率吗?
[/Quote]
数组是线性的。
map是树形的。
zw1987122 2010-04-08
  • 打赏
  • 举报
回复
学习了............
ztenv 版主 2010-04-08
  • 打赏
  • 举报
回复
勉强可以,注意越界问题;
zjhzstudent 2010-04-08
  • 打赏
  • 举报
回复
class CMD
{
public:
virtual void printMsg()=0;

};

class CMD_1:CMD
{
public:
void printMsg(){printf("xx1\n");}
};
class CMD_2:CMD
{
public:
void printMsg(){printf("xx2\n");}
};
class CMD_3:CMD
{
public:
void printMsg(){printf("xx3");}
};


CMD* m_CMDArray[CMD_Max];
m_CMDArray[cmd1]= new CMD_1();
m_CMDArray[cmd2]= new CMD_2();
m_CMDArray[cmd3]= new CMD_3();


m_CMDArray[cmd]->printMsg();

这样写好像符合简单工厂模式 有利于扩展吧,我想
only_delusion 2010-04-08
  • 打赏
  • 举报
回复
学习了............
ztenv 版主 2010-04-08
  • 打赏
  • 举报
回复
[Quote=引用 32 楼 fz_zhou 的回复:]
不用考虑这种优化,微不足道。

真的费CPU的往往不会在你自己写的代码,都是系统调用。
[/Quote]
可以说这是一种写代码的境界。。。。。。也许有点“孔乙己”了,但程序员就应该有这种精神!
我不是大明 2010-04-08
  • 打赏
  • 举报
回复
不用考虑这种优化,微不足道。

真的费CPU的往往不会在你自己写的代码,都是系统调用。


lx_xproer 2010-04-08
  • 打赏
  • 举报
回复
你为什么不直接向你领导问一句,为什么要消除 switch case ?
ztenv 版主 2010-04-08
  • 打赏
  • 举报
回复
8楼的代码:
不觉得是为了用继承而用继承吗?这里完全可以不用继承,而设置一个变量,为变量赋值不同而打印不同的结果;
当然如果你的cmd有不同的执行方式,则可以用8楼的代码;

关于28楼的,只不过是把switch换了个地方而已,扩展起来简单一些(毕竟只用修改工厂),但数量多了一样效率低下和麻烦;您不觉得吗?

在28楼的factory中,一样需要消除switch语句,至于怎么消除有多种方法了,楼上的几位也有提到过,
dhc_6huoCangLong 2010-04-08
  • 打赏
  • 举报
回复
感谢各位 呵呵呵
看到这么多回帖 太激动了
祝大家天天快乐!身体健康!
hntoitx 2010-04-08
  • 打赏
  • 举报
回复
采用简单工厂模式设计吧!
我引用一下8楼的代码,加上工厂.

class CMD
{
public:
virtual void printMsg()=0;

};

class CMD_1:CMD
{
public:
void printMsg(){printf("xx1\n");}
};
class CMD_2:CMD
{
public:
void printMsg(){printf("xx2\n");}
};
class CMD_3:CMD
{
public:
void printMsg(){printf("xx3");}
};

class CMDFactory
{
public:
CMD* CreateCMD( CMD_TYPE type )
{
CMD* pCMD = NULL;
switch( type )
{
case cmd1:
{
pCMD = new CMD_1;
}break;
case cmd2:
{
pCMD = new CMD_2;
}break;

case cmd3:
{
pCMD = new CMD_3;
}break;


}
}

return pCMD;
};

void main()
{
CMDFactory factory;
CMD* pCMD = NULL;

pCMD = factory.CreateCMD( cmd1 );
pCMD ->printMsg();
}

macrojj 2010-04-07
  • 打赏
  • 举报
回复
把switch全部都消灭。。。

有什么好处呢
FrankSun80 2010-04-07
  • 打赏
  • 举报
回复
说实话,一刀切的消除所有的Switch case,好嘛?
赵4老师 2010-04-07
  • 打赏
  • 举报
回复
VC调试时按Alt+8,TC或BC用TD调试,打开汇编窗口看每句C对应的汇编不就啥都明白了吗。
cocat 2010-04-07
  • 打赏
  • 举报
回复
呵呵~还有不用switch一说啊~~
chenchangxiong 2010-04-07
  • 打赏
  • 举报
回复
只有反射才能彻底消除switch(据我所知),可惜c++不支持这种操作。。。。
所以。。。。。。
okeyes 2010-04-07
  • 打赏
  • 举报
回复
消除switch case是为了以后,增添程序功能更方便.
haosuai 2010-04-07
  • 打赏
  • 举报
回复
下面是个比较的代码

int li_tmp = 1;
switch(li_tmp)
{
case 1:
printf("11");
break;
case 2:
printf("22");
break;
case 3:
printf("33");
break;
}
对应的汇编是
00401028 mov dword ptr [ebp-4],1
0040102F mov eax,dword ptr [ebp-4]
00401032 mov dword ptr [ebp-8],eax
00401035 cmp dword ptr [ebp-8],1
00401039 je main+39h (00401049)
0040103B cmp dword ptr [ebp-8],2
0040103F je main+48h (00401058)
00401041 cmp dword ptr [ebp-8],3
00401045 je main+57h (00401067)
00401047 jmp main+64h (00401074)
00401049 push offset string "11" (00420f24)
0040104E call printf (004010b0)
00401053 add esp,4
00401056 jmp main+64h (00401074)
00401058 push offset string "22" (0042012c)
0040105D call printf (004010b0)
00401062 add esp,4
00401065 jmp main+64h (00401074)
00401067 push offset string "33" (0042001c)
0040106C call printf (004010b0)
00401071 add esp,4


第二种:不使用SWITCH
char * lz_tmp[3];
lz_tmp[0] = "11";
lz_tmp[1] = "22";
lz_tmp[2] = "33";
printf("%s",lz_tmp[0]);
对应的汇编
0401010 push ebp
00401011 mov ebp,esp
00401013 sub esp,4Ch
00401016 push ebx
00401017 push esi
00401018 push edi
00401019 lea edi,[ebp-4Ch]
0040101C mov ecx,13h
00401021 mov eax,0CCCCCCCCh
00401026 rep stos dword ptr [edi]
00401028 mov dword ptr [ebp-0Ch],offset string "11" (00420f24)
0040102F mov dword ptr [ebp-8],offset string "22" (0042012c)
00401036 mov dword ptr [ebp-4],offset string "33" (0042001c)
0040103D mov eax,dword ptr [ebp-0Ch]
00401040 push eax
00401041 push offset string "%s" (004207b0)
00401046 call printf (004010b0)
0040104B add esp,8


可以看到单单从汇编的指令来看:
使用SWITCH的代码最理想的情况是1次比较,1次条件比较跳转,执行printf 。最坏的情况是5次比较(条件比较失败2次+比较3次),1次条件比较跳转,执行printf。
不使用SWITCH的代码可以看到是真正的操作只要一次的数据转移就可以了,所以单单从汇编代码上看,使用第二种速度要更快。
但是现在的CPU的流水线技术使得某些不相关指令可以并行或乱序执行,以致于每个操作指令的周期是难以确定的,在加上CPU可能会对一些SWITCH出来的汇编指令进行优化,所以实际的速度情况可能不会相差那么大。
要确定更准确的速度,需要熟悉CPU的大大出来指点了
hntoitx 2010-04-06
  • 打赏
  • 举报
回复
估计你领导是想让你使用面向对象清除。C++最重要的是面向对象设计,而不是面向过程。而你现在写的代码就是面向过程来设计的。
加载更多回复(18)

64,637

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧