Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/127.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 性能差异;如果“如果”;vs";如果是,如果不是;_C++_C - Fatal编程技术网

C++ 性能差异;如果“如果”;vs";如果是,如果不是;

C++ 性能差异;如果“如果”;vs";如果是,如果不是;,c++,c,C++,C,我只是在想C/C++中的两个语句之间是否有性能差异: 案例1: if (p==0) do_this(); else if (p==1) do_that(); else if (p==2) do_these(): 案例2: if(p==0) do_this(); if(p==1) do_that(); if(p==2) do_these(); 在前一种情况下,不评估匹配后的条件。是,性能差异为: 第二条语句计算每个IF对于数量有限的表达式,您可能不会注

我只是在想C/C++中的两个语句之间是否有性能差异:

案例1:

if (p==0)
   do_this();
else if (p==1)
   do_that();
else if (p==2)
   do_these():
案例2:

if(p==0)
    do_this();
if(p==1)
    do_that();
if(p==2)
    do_these();

在前一种情况下,不评估匹配后的条件。

是,性能差异为:


第二条语句计算每个IF

对于数量有限的表达式,您可能不会注意到性能上的任何差异。但是理论上,
if..if..if
需要检查每个表达式。如果单个表达式相互排斥,则可以使用
If..else If..
来保存该计算。这样,只有在前面的案例失败时,才会检查另一个表达式

请注意,在检查int是否相等时,也可以使用
switch
语句。这样,您仍然可以为长序列的检查保持一定程度的可读性

switch ( p )
{
    case 0:
        do_this();
        break;

    case 1:
        do_that();
        break;

    case 2:
        do_these():
        break;
}

主要区别在于,一旦其中一个返回true,if/else构造将停止计算ifs()。这意味着在保释之前,它只能执行1或2个ifs。另一个版本将检查所有3个ifs,而不管其他版本的结果如何

所以。。。。if/else的运营成本为“最多3次检查”。if/if/if版本的运行成本为“始终进行3次检查”。假设所有3个被检查值的可能性相同,则if/else版本将执行平均1.5个ifs,而if/if版本将始终执行3个ifs。从长远来看,使用“else”构造可以节省相当于1.5 ifs的CPU时间。

假设类型简单(在本例中,我使用了
int
),并且没有有趣的事情(没有为int重新定义operator=),至少在AMD64上使用GCC4.6,没有区别。生成的代码相同:

0000000000000000 <case_1>:                                   0000000000000040 <case_2>:
   0:   85 ff                   test   %edi,%edi               40:   85 ff                   test   %edi,%edi
   2:   74 14                   je     18 <case_1+0x18>        42:   74 14                   je     58 <case_2+0x18>
   4:   83 ff 01                cmp    $0x1,%edi               44:   83 ff 01                cmp    $0x1,%edi
   7:   74 27                   je     30 <case_1+0x30>        47:   74 27                   je     70 <case_2+0x30>
   9:   83 ff 02                cmp    $0x2,%edi               49:   83 ff 02                cmp    $0x2,%edi
   c:   74 12                   je     20 <case_1+0x20>        4c:   74 12                   je     60 <case_2+0x20>
   e:   66 90                   xchg   %ax,%ax                 4e:   66 90                   xchg   %ax,%ax
  10:   f3 c3                   repz retq                      50:   f3 c3                   repz retq 
  12:   66 0f 1f 44 00 00       nopw   0x0(%rax,%rax,1)        52:   66 0f 1f 44 00 00       nopw   0x0(%rax,%rax,1)
  18:   31 c0                   xor    %eax,%eax               58:   31 c0                   xor    %eax,%eax
  1a:   e9 00 00 00 00          jmpq   1f <case_1+0x1f>        5a:   e9 00 00 00 00          jmpq   5f <case_2+0x1f>
  1f:   90                      nop                            5f:   90                      nop
  20:   31 c0                   xor    %eax,%eax               60:   31 c0                   xor    %eax,%eax
  22:   e9 00 00 00 00          jmpq   27 <case_1+0x27>        62:   e9 00 00 00 00          jmpq   67 <case_2+0x27>
  27:   66 0f 1f 84 00 00 00    nopw   0x0(%rax,%rax,1)        67:   66 0f 1f 84 00 00 00    nopw   0x0(%rax,%rax,1)
  2e:   00 00                                                  6e:   00 00 
  30:   31 c0                   xor    %eax,%eax               70:   31 c0                   xor    %eax,%eax
  32:   e9 00 00 00 00          jmpq   37 <case_1+0x37>        72:   e9 00 00 00 00          jmpq   77 <case_2+0x37>
  37:   66 0f 1f 84 00 00 00    nopw   0x0(%rax,%rax,1)
  3e:   00 00 
0000000000000000:00000000000000 40:
0:85 ff测试%edi,%edi 40:85 ff测试%edi,%edi
2:74 14日本脑炎18 42:74 14日本脑炎58
4:83 ff 01 cmp$0x1,%edi 44:83 ff 01 cmp$0x1,%edi
7:7427JE3047:7427JE70
9:83 ff 02 cmp$0x2,%edi 49:83 ff 02 cmp$0x2,%edi
c:7412JE204C:7412JE60
e:66 90 xchg%ax,%ax 4e:66 90 xchg%ax,%ax
10:f3 c3重复调整50:f3 c3重复调整
12:66 0f 1f 44 00 00 nopw 0x0(%rax,%rax,1)52:66 0f 1f 44 00 nopw 0x0(%rax,%rax,1)
18:31 c0异或%eax,%eax 58:31 c0异或%eax,%eax
1a:e9 00 00 jmpq 1f 5a:e9 00 00 jmpq 5f
1f:90 nop 5f:90 nop
20:31 c0异或%eax,%eax 60:31 c0异或%eax,%eax
22:e9 00 00 jmpq 27 62:e9 00 00 jmpq 67
27:66 0f 1f 84 00 00 nopw 0x0(%rax,%rax,1)67:66 0f 1f 84 00 nopw 0x0(%rax,%rax,1)
2e:00 6e:00
30:31 c0异或%eax,%eax 70:31 c0异或%eax,%eax
32:e9 00 00 jmpq 37 72:e9 00 00 jmpq 77
37:66 0f 1f 84 00 nopw 0x0(%rax,%rax,1)
3e:00
案例_1末尾的额外指令仅用于


这并不奇怪,发现p在该函数中没有改变是相当基本的优化。如果p可以更改(例如,通过引用或指针传递到各种
do.
函数,或者是引用或指针本身,因此可能存在别名),那么行为就不同了,当然生成的代码也会不同。

正如已经演示的那样。。。情况各不相同

如果我们谈论的是像
int
这样的基本(内置)类型,那么编译器可能足够聪明,所以它不重要(或者不重要)。但是,无论如何,性能影响都很小,因为调用函数的成本远远高于if调用函数的成本,因此,如果您试图测量函数的差异,则差异可能会消失在噪声中

然而,语义是完全不同的

当我读到第一个案例时:

if (...) {
  // Branch 1
} else if (...) {
  // Branch 2
}
然后我知道,无论这两个分支做什么,都只能执行一个分支

然而,当我读到第二个案例时:

if (...) {
}
if (...) {
}
然后,我不得不考虑是否有可能同时使用这两个分支,这意味着我必须仔细检查第一个分支中的代码,以确定它是否可能影响第二个测试。当我最终得出结论时,我诅咒了一个该死的开发人员,他太懒了,不肯写那该死的
否则的
,这本可以让我省下最后10分钟的审查时间

因此,请帮助您自己和您未来的维护人员,并集中精力使语义正确和清晰


在这个问题上,有人可能会说,也许这个分派逻辑可以用其他结构更好地表达,比如
开关
,或者
映射
?(注意后者,避免过度工程化;)

如果其他的更快的话;如果在最后一个if之前找到匹配,则至少跳过最后一个if语句,如果在第一个if中找到匹配,则将跳过所有其他语句

如果速度较慢;即使我们找到了匹配的人