V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
hyd8323268
V2EX  ›  程序员

提问: ifelse 语句和 switch 语句,除了 if 可以更加具体的判断外,两者还有什么区别呢,各自在什么情况下使用更好

  •  1
     
  •   hyd8323268 · 2019-06-25 10:22:26 +08:00 · 5059 次点击
    这是一个创建于 1977 天前的主题,其中的信息可能已经有所发展或是发生改变。

    提问: ifelse 语句和 switch 语句,除了 if 可以更加具体的判断外,两者还有什么区别呢,各自在什么情况下使用更好

    42 条回复    2019-06-28 10:30:47 +08:00
    hyd8323268
        1
    hyd8323268  
    OP
       2019-06-25 10:25:12 +08:00
    刚刚看了看博客说 switch 会比 if 效率更好点,但是具体为什么好呢,好多少
    kzfile
        2
    kzfile  
       2019-06-25 10:26:52 +08:00
    我好像在一些地方看到推荐用 if/else 替换 switch
    chendy
        3
    chendy  
       2019-06-25 10:33:52 +08:00
    有的语言(我只知道 kotlin ),case 里可以放条件判断,效果相当于一串 if-else-if
    不考虑这个,switch 在一些情况下性能比一串判断好,毕竟只有一次判断,ifelse 可能要判断很多次才能走到复合条件的分支
    最后其实还是“具体情况具体分析”,用哪种写起来清晰已读就用哪种
    hyd8323268
        4
    hyd8323268  
    OP
       2019-06-25 10:35:18 +08:00
    if 语句会从第一个判断开始,挨个过,直到满足条件。而 switch 会创建一个类似数组的东西,然后把每个 case 内的条件放入,如果需要判断的值是数字,则去判断数组中最大值是否大于变量,小于则直接走 default,如果大于则再走指定 case。

    大概是这样吗
    misaka19000
        5
    misaka19000  
       2019-06-25 10:35:57 +08:00
    这个问题,要具体语言具体分析
    annielong
        6
    annielong  
       2019-06-25 10:53:13 +08:00   ❤️ 1
    反正个人用的时候判断条件超过 3 个就使用 switch,不超过就用 if
    glishijie
        7
    glishijie  
       2019-06-25 11:10:41 +08:00 via Android
    不同语言语义是不同的,c 语言 case 只能是常数值,不能是表达式,switch 实现的时候通常会有 switch table,可以减小 cache Miss,性能会好一点
    cnzjl
        8
    cnzjl  
       2019-06-25 11:14:59 +08:00
    使用 switch..case 应该是更好维护点,你想想 10 个条件在那使用 if...else,然后 switch 的匹配好像是随机的吧,确定了选择值就直接跳过去了,如果是 if 的话就要一步一步走下去,条件多的时候还是推荐 switch
    shendaowu
        9
    shendaowu  
       2019-06-25 11:29:04 +08:00   ❤️ 1
    switch 在一定条件下时间复杂度好像可以达到 O(1)。有兴趣可以搜搜“查表法”。这篇好像不错: https://www.jianshu.com/p/3efd6ca8011f。switch 在某些条件下应该是可以优化成类似查表法的东西,我不太确定。楼主如果懂汇编语言的话写一些不同的 switch 语句然后看汇编代码会很好玩的。我之前好像就是在看汇编代码的时候发现 switch 和 if 的区别的。
    shendaowu
        10
    shendaowu  
       2019-06-25 11:29:34 +08:00
    pkookp8
        11
    pkookp8  
       2019-06-25 11:30:12 +08:00 via Android
    什么语言
    试了下 c 语言,x86 的 gcc,差了一条指令
    对 x86 汇编不太熟还没仔细看
    shawndev
        12
    shawndev  
       2019-06-25 11:30:18 +08:00
    有模式匹配的语言,switch case 表达力更强。没有模式匹配的语言,多数情况下 switch case 可以使用表驱动法开发。
    xuanbg
        13
    xuanbg  
       2019-06-25 11:31:03 +08:00
    if()需要按顺序一个个 else if()进行判断执行代码块还是跳出,switch 直达条件所在代码块执行。所以只有一个 if/else 两者没区别,else if 越多区别越大。当然,switch 虽好,不符合条件也是用不了的。
    xuanbg
        14
    xuanbg  
       2019-06-25 11:36:01 +08:00
    @chendy case 里可以放条件判断,效果并不是相当于一串 if-else-if。case 里的条件只是第二次 match 罢了,不成功就结束了,不会再去 match 下一个 case
    dangyuluo
        15
    dangyuluo  
       2019-06-25 11:37:36 +08:00
    现代编译器足够聪明,在条件不造成其他影响的情况下,能够自动将二者转换,挑选效率最高的那个,放心交给编译器去做就可以了,实在害怕可以看一下出来的汇编代码。

    当然你也可以添加分支预测语句`likely(xxx)`,不过一般这时候你也成大牛了。
    wysnylc
        16
    wysnylc  
       2019-06-25 12:27:12 +08:00
    在 java 中 if else if else 是从上往下逐个匹配,在上百个判断时效率极低,此时 switch 可以站出来了因为时间复杂度是 O(1)
    然后还有一种是使用 treeMap 可以做范围条件匹配,简单讲是能用 switch 和 treeMap 就用不行再考虑 if else
    maokabc
        17
    maokabc  
       2019-06-25 12:42:00 +08:00 via Android
    其他不清楚,java 整数 switch 的话会被编译为 table-switch 或者 lookup-switch,对应查表法和二分法
    Shy07
        18
    Shy07  
       2019-06-25 12:54:59 +08:00
    弱类型的建议用 if else 严格判断
    switch 建议用 hash/array/map/object + closure 的方式更 FP
    ragnaroks
        19
    ragnaroks  
       2019-06-25 13:45:17 +08:00
    if 可以对应多个判断项,比如`object1!=null && object1.value1 is Int32`,不过如果是 C#的话,7+以上区别不大了,switch 也可以匹配多个表达式
    springmarker
        20
    springmarker  
       2019-06-25 14:06:36 +08:00
    一个是静态的,一个是动态的
    yedanten
        21
    yedanten  
       2019-06-25 15:07:21 +08:00
    可以写个小 demo,然后逆向一下就知道了。这里写两个 demo 给 LZ 解释一下。
    两个 demo 编译都是采用 gcc -O0 的方式
    先看 if 的,代码如下。
    ![ifcode]( https://imgur.com/3Nc8Nzl)

    在看逆向之后的结果
    ![ifreverse]( https://imgur.com/6IkQxQ2)
    和代码所写的判断顺序一样,逐个判断。

    在看 switch 的,代码如下。
    ![switchcode]( https://imgur.com/9PBOKmz)

    逆向结果
    ![switchreverse]( https://imgur.com/Ox2qH4C)
    第一次判断和数值 2 对比,后续采用大于还是小于,进行二分法逐层判断。

    所以在写 C/C++的时候,关闭编译器优化的情况下,如果判断分支比较多,采用 switch 效率会更高。

    然后在吐个槽……分支真的那么多的时候,是不是应该考虑优化业务逻辑了
    yedanten
        22
    yedanten  
       2019-06-25 15:08:32 +08:00
    @yedanten 摔,为什么 markdown 格式发图失败了……
    hyd8323268
        23
    hyd8323268  
    OP
       2019-06-25 15:58:45 +08:00
    @shendaowu 感谢 晚上回去看看
    hyd8323268
        24
    hyd8323268  
    OP
       2019-06-25 16:01:21 +08:00
    @yedanten 兄弟你链接挂了
    labnotok
        25
    labnotok  
       2019-06-25 16:05:16 +08:00 via Android
    由于每个 case 的出现概率不同,
    if else 可以利用先验知识优化,
    达到实际中的最小复杂度。
    yedanten
        26
    yedanten  
       2019-06-25 16:08:25 +08:00 via Android
    @hyd8323268 额,这个图床要搭梯子……
    psychoo
        27
    psychoo  
       2019-06-25 16:37:03 +08:00
    试了一下 C 语言 1 亿次的 11 条件 if 和 switch,if 比 switch 快一点,不知原因
    wym7223645
        28
    wym7223645  
       2019-06-25 17:10:52 +08:00
    java 项目,我们项目要求你使用 if-else 不建议使用 switch,原因就是 业务变化太快,分分钟的加上复杂条件
    jaskle
        29
    jaskle  
       2019-06-25 19:14:35 +08:00 via Android
    其实吧,与语言有关,如果是脚本类还是 if 吧,Java 判断量多的可以用用 switch,c 系的只有数值接近或递增规律明显才会用跳表。总结:哪个方便用哪个,除非你的性能瓶颈不在 io 上,这点性能损耗也就 12306 能用上
    secondwtq
        30
    secondwtq  
       2019-06-25 19:40:37 +08:00 via iPad
    secondwtq
        31
    secondwtq  
       2019-06-25 19:43:07 +08:00 via iPad
    @yedanten 为什么要关优化?
    你可以去看下 LLVM 的代码,大块的 switch 满天飞
    dremy
        32
    dremy  
       2019-06-25 19:56:54 +08:00 via iPhone
    自以为比编译器聪明系列
    yedanten
        33
    yedanten  
       2019-06-25 20:54:03 +08:00 via Android
    @secondwtq 这不是为了给楼主演示 if 和 switch 在编译后是怎么执行的,才关掉优化嘛,开着优化那反汇编出来的都是二分法判断。
    weixiangzhe
        34
    weixiangzhe  
       2019-06-25 22:23:42 +08:00
    python 就没有 switch 吧,还是看语言吧
    pan519
        35
    pan519  
       2019-06-26 01:41:14 +08:00
    小白也有类似疑问。。。switch 不是后面只能写 int string 类的嘛?
    csys
        36
    csys  
       2019-06-26 02:19:51 +08:00 via Android
    取决于有没有模式匹配
    msg7086
        37
    msg7086  
       2019-06-26 03:11:09 +08:00
    怎么写舒服怎么写。这种细节上的效率优化带来的性能提升太小了。真的遇到性能瓶颈了再做 Profiling 不迟。
    hallwoodzhang
        38
    hallwoodzhang  
       2019-06-26 05:04:49 +08:00 via Android
    switch 语句会直接通过条件查表,然后通过 offset 跳到对应指令,if 则没这么快
    zwh2698
        39
    zwh2698  
       2019-06-26 07:12:30 +08:00 via Android   ❤️ 2
    科普编译器跳转表,很多 switch 语句编译器在后期都把它转成跳转表,而一般的 if 语句就是汇编的大于等于小于跳转,两个执行的代码多少不同。关键来了:现代编译器对 if 语句一定多个一起的也会做成跳转表,比较少的,就在 peephole 优化阶段删掉更多的无用语句,也不会差很多。
    Mohanson
        40
    Mohanson  
       2019-06-26 09:32:05 +08:00 via Android
    语义不同
    ysn2233
        41
    ysn2233  
       2019-06-26 11:26:28 +08:00
    现在来说,不带模式匹配的语言感觉没什么区别了都
    hyd8323268
        42
    hyd8323268  
    OP
       2019-06-28 10:30:47 +08:00
    @zwh2698 感谢
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3377 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 36ms · UTC 04:45 · PVG 12:45 · LAX 20:45 · JFK 23:45
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.