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

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

  •  1
     
  •   hyd8323268 · 142 天前 · 2921 次点击
    这是一个创建于 142 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

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

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

    当然你也可以添加分支预测语句`likely(xxx)`,不过一般这时候你也成大牛了。
        16
    wysnylc   142 天前
    在 java 中 if else if else 是从上往下逐个匹配,在上百个判断时效率极低,此时 switch 可以站出来了因为时间复杂度是 O(1)
    然后还有一种是使用 treeMap 可以做范围条件匹配,简单讲是能用 switch 和 treeMap 就用不行再考虑 if else
        17
    maokabc   142 天前 via Android
    其他不清楚,java 整数 switch 的话会被编译为 table-switch 或者 lookup-switch,对应查表法和二分法
        18
    Shy07   142 天前
    弱类型的建议用 if else 严格判断
    switch 建议用 hash/array/map/object + closure 的方式更 FP
        19
    ragnaroks   142 天前
    if 可以对应多个判断项,比如`object1!=null && object1.value1 is Int32`,不过如果是 C#的话,7+以上区别不大了,switch 也可以匹配多个表达式
        20
    springmarker   142 天前
    一个是静态的,一个是动态的
        21
    yedanten   142 天前
    可以写个小 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 效率会更高。

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