如果是c ++语句

时间:2010-02-02 09:38:24

标签: c++ data-structures

Hay亲爱的!

我知道if语句在c ++中是一个昂贵的语句。我记得,一旦我的老师说,如果声明在计算机时间意义上是一个昂贵的陈述。

现在我们可以通过在c ++中使用if语句来做所有事情,因此这在编程透视图中是非常强大的语句,但在计算机时间透视图中它很昂贵。

我是初学者,在介绍c ++课程后我正在学习数据结构课程。 我的问题是
我是否更好地使用if语句进行扩展?

10 个答案:

答案 0 :(得分:17)

如果语句被编译为conditional branch。这意味着处理器必须跳转(或不跳转)到另一行代码,具体取决于条件。在一个简单的处理器中,这可能会导致pipeline stall,这在外行人的意义上意味着处理器必须尽早丢弃它所做的工作,这会浪费在装配线上的时间。但是,现代处理器使用branch prediction来避免停顿,因此如果语句变得更便宜。

总之,是的,它们可能很昂贵。不,你一般不应该担心它。但Mykola提出了一个单独的(虽然同样有效)的观点。对于if或case语句,Polymorphic code通常更可取(对于可维护性)

答案 1 :(得分:13)

我不确定如何推断if语句很昂贵。

如果你有

if ( true ) { ... }

然后你的编译器会最优化if

另一方面,如果你有...

if ( veryConvolutedMethodTogGetAnswer() ) { .. }

并且方法veryConvolutedMethodTogGetAnswer()做了很多工作,你可以说这是一个昂贵的if语句,但不是因为if,而是因为你在决策过程中所做的工作。 / p>

“如果”在时钟周期方面本身通常不“昂贵”。

答案 2 :(得分:7)

过早优化是一个坏主意。在有意义的情况下使用if语句。当您发现代码的一部分需要改进其性能时,可能会从代码的那一部分中删除if语句。

如果语句很昂贵,因为它们会强制编译器生成分支指令。如果你能找到一种方法来编写相同的逻辑,那么即使有更多的总指令,编译器也不必完全分支,代码可能会快得多。我记得对于如何重新编码一小段代码以使用各种位操作而不是进行任何分支加速10-20%的事情,我感到非常惊讶。

但这并不是一般避免它们的理由。当你试图从一段你知道性能至关重要的代码中榨取最后一点速度时,请记住这一点,因为你已经运行了一个分析器和各种其他工具来证明这一点。

如果陈述费用昂贵,另一个原因是因为它们会增加程序的复杂性,使其难以阅读和维护。保持低功能的复杂性。不要使用过多的语句来通过你的函数创建不同的控制路径。

答案 3 :(得分:5)

我认为从可维护性的角度来看,很多 if statement代价很高。

答案 4 :(得分:2)

if语句意味着条件分支可能比不分支的代码贵一点。

例如,计算条件为真的次数(例如,向量中的多少个数字大于10000):

for (std::vector<int>::const_iterator it = v.begin(), end = v.end(); it != end; ++it) {
    //if (*it > 10000) ++count; 
    count += *it > 10000;
}

简单地将1或0添加到运行总计中的版本可能会更快(我尝试使用1亿个数字然后才能辨别出差异)。

但是,使用MinGW 3.4.5时,使用专用的标准算法会明显显着

count = std::count_if(v.begin(), v.end(), std::bind2nd(std::greater<int>(), 10000));

所以我们的教训是,在开始优化之前,使用从互联网上学到的一些技巧,您可以尝试使用该语言的推荐实践。 (当然首先要确保程序的那一部分首先是不合理的缓慢。)

另一个经常避免评估复杂条件的地方是使用查找表(根据经验:如果你让它们使用更多内存,通常可以加快算法速度)。例如,在单词列表中计算元音(aeiou),您可以避免分支和评估多个条件:

unsigned char letters[256] = {0};
letters['a'] = letters['e'] = letters['i'] = letters['o'] = letters['u'] = 1; 

for (std::vector<std::string>::const_iterator it = words.begin(), end = words.end(); it != end; ++it) {
    for (std::string::const_iterator w_it = it->begin(), w_end = it->end(); w_it != w_end; ++w_it) {
        unsigned char c = *w_it;
        /*if (c == 'e' || c == 'a' || c == 'i' || c == 'o' || c == 'u') {
            ++count;
        }*/
        count += letters[c];
    }
} 

答案 5 :(得分:1)

您应该编写正确,易于理解且易于维护的代码。如果这意味着使用if语句,请使用它们!我觉得很难相信有人建议你不要使用if声明。

也许你的导师意味着你应该避免这样的事情:

if (i == 0) {
    ...
} else if (i == 1) {
    ...
} else if (i == 2) {
    ...
} ...

在这种情况下,重新考虑您的数据结构和/或算法可能更合乎逻辑,或者至少使用switch/case

switch (i) {
    case 1: ...; break;
    case 2: ...; break;
    ...;
    default: ...; break;
}

但即便如此,由于提高了可读性而非效率,因此上述情况更好。如果你真的需要效率,那么诸如消除if条件之类的事情可能是一个糟糕的开始。您应该改为编写代码,并找出瓶颈所在。

简短回答:当且仅当它有意义时才使用if

答案 6 :(得分:0)

就计算机时间而言,“if”语句本身就是最便宜的陈述之一。

当有更好的方式(如开关或哈希表)时,不要将其中的20个连续放入,并且你会做得很好。

答案 7 :(得分:0)

您可以使用Switch来提高可读性,但如果速度更快,我就不会这样做。如果你有类似的东西:

if (condition1) {
   // do something
} else if (condition2) {
   // do something
} else if (condition3) { 
   // do something
} else if (condition4) { 
   // do something
}

我不是可以做些什么来加快速度。如果更频繁地发生condition4,您可以将其移至顶部。

答案 8 :(得分:0)

数据结构过程中,if语句的性能无关紧要。 if语句与任何晦涩的替代方案之间的微小差异完全被数据结构之间的差异所淹没。例如,在以下伪代码中

FOR EACH i IN container
  IF i < 100
    i = 100
  container.NEXT(i)
END FOR

表现最多由container.NEXT(i)决定;这对链表来说要贵得多,那么对于连续的数组来说也是如此。对于链表,这需要额外的内存访问,这取决于缓存可能需要介于2.5 ns和250 ns之间。 if语句的成本将以几纳秒的分数来衡量。

答案 9 :(得分:0)

由于许多if语句在批处理脚本中调用内部循环,我确实遇到了性能问题,因此我使用整数数学来模拟if语句,并且它大大提高了性能。

    if [%var1%] gtr [1543]
        set var=1
    else
        set var=0

相当于

    set /a var=%var1%/1543

我甚至使用了更多更长的表达式,使用了很多/和%的操作,并且它仍优于if语句。

我知道这不是C ++,但我猜是同样的原则。因此,无论何时需要性能,都要尽量避免使用条件语句。