函数返回在“if”的分支中,与“if”的分支,在C++

Function return in branches of an `if` vs outside the `if`, in C++

本文关键字:分支 if C++ 函数 返回      更新时间:2023-10-16

编译的代码是否有差异

double func(bool x) {
  if (x) {
    return 1.0;
  } else {
    return 2.0;
  };
}

double func(bool x){
  if (x) {
    return 1.0;
  };
  return 2.0;
}

是否有性能原因偏袒其中一种?

我唯一知道的是打字速度快的秒。


我一直在使用 g++,但如果它不同,了解其他人会发生什么会很有趣。

这里没有性能差异,因为一旦编译器采用"then"分支,"else"分支就变得无法访问。优化编译器生成的代码应相同。

示例的可读性也不会改变。但是,当else分支很长而"then"分支很短时,第二个代码段读取得更好,因为它的嵌套级别较低。

"

then"分支较短而"else"分支较长的情况非常常见 - 当您执行参数检查时,会发生这种情况,并在参数超出范围时引发异常或提供提前终止。当您考虑在函数顶部进行多次验证时,第二种方法的优势变得更加明显,例如

if (!arg1.isInRange()) {
    return FAILURE_REASON_1;
} else {
    if (!arg2.isInRange()) {
        return FAILURE_REASON_2;
    } else {
        if (!arg3.isInRange()) {
            return FAILURE_REASON_3;
        } else {
            ... // Payload code goes here
        }
    }
}

与。

if (!arg1.isInRange()) {
    return FAILURE_REASON_1;
}
if (!arg2.isInRange()) {
    return FAILURE_REASON_2;
}
if (!arg3.isInRange()) {
    return FAILURE_REASON_3;
}
... // Payload code goes here
"编译

的代码之间是否存在差异"无论如何都是一个糟糕的开始。程序集输出未由C++标准指定,只是它必须反映标准中声明的规则。无论每条指令之间有或没有一百万次无操作 - 在大多数情况下,它同样一致。因此,使用标准作为参考,您无法对实际程序集输出进行任何说明,因为它依赖于使用的实际编译器。
对于有关的问题,您需要指定编译器和版本,操作系统,体系结构等。否则,只需自己编译和比较程序集输出。

无论如何,为了解决您的实际问题,输出应该与体面的编译器不同。


在我的 x86-64 带有 GCC 5.2.0 的机器上:

第一:

   0:   55                      push   %rbp
   1:   48 89 e5                mov    %rsp,%rbp
   4:   89 f8                   mov    %edi,%eax
   6:   88 45 fc                mov    %al,-0x4(%rbp)
   9:   80 7d fc 00             cmpb   $0x0,-0x4(%rbp)
   d:   74 0a                   je     19 <_Z5func0b+0x19>
   f:   f2 0f 10 05 00 00 00    movsd  0x0(%rip),%xmm0
  16:   00 
  17:   eb 08                   jmp    21 <_Z5func0b+0x21>
  19:   f2 0f 10 05 00 00 00    movsd  0x0(%rip),%xmm0
  20:   00 
  21:   5d                      pop    %rbp
  22:   c3                      retq

第二:

  23:   55                      push   %rbp
  24:   48 89 e5                mov    %rsp,%rbp
  27:   89 f8                   mov    %edi,%eax
  29:   88 45 fc                mov    %al,-0x4(%rbp)
  2c:   80 7d fc 00             cmpb   $0x0,-0x4(%rbp)
  30:   74 0a                   je     3c <_Z5func1b+0x19>
  32:   f2 0f 10 05 00 00 00    movsd  0x0(%rip),%xmm0
  39:   00 
  3a:   eb 08                   jmp    44 <_Z5func1b+0x21>
  3c:   f2 0f 10 05 00 00 00    movsd  0x0(%rip),%xmm0
  43:   00 
  44:   5d                      pop    %rbp
  45:   c3                      retq   

不要不同。

对于初学者来说,没有必要包含一个空语句

double func(bool x) {
  if (x) {
    return 1.0;
  } else {
    return 2.0;
  };
  ^^^
}

至于这个问题,编译器可以为两个函数生成相同的目标代码。

但对我来说,我更喜欢以下功能:)

double func( bool x ) { return x ? 1.0 : 2.0; }

我不排除编译器可以生成与您帖子中的前两个函数相同的目标代码。

此外,它本身可以使函数内联。

因此,相对于这些函数,唯一可能存在的问题是哪一个更具可读性。

至于你展示的函数,第一个与第二个相比更具可读性,前提是函数中没有其他语句。阅读第二个函数的代码,我会花一些时间自己回答为什么没有使用else的问题:)