【问题标题】:Best practice for having two if statements from the same bool c++来自同一个 bool c++ 的两个 if 语句的最佳实践
【发布时间】:2012-07-19 11:09:00
【问题描述】:

我有一个 if 语句 [显然] 仅在条件为真时运行。在这个 if 语句之后有一些代码应该始终运行,然后是另一个 if 语句应该在与第一个相同的条件下运行。

中间的代码使用堆栈的特定元素执行操作,两边的ifs分别在操作之前和之后对堆栈执行push/pop。

所以逻辑是这样的:

  1. 我需要推送堆栈吗?是/否
  2. 在堆栈顶部执行操作
  3. 堆栈是否被推送? (如果是,则弹出)

第 1 项和第 3 项条件相同。

这是我第一次用 c++ 编写的代码

#include <stdio.h>
#include <stdlib.h>

int somefunction(){
    return rand() % 3 + 1; //return a random number from 1 to 3
}

int ret = 0;


//:::::::::::::::::::::::::::::::::::::::
//  Option 1 Start
//:::::::::::::::::::::::::::::::::::::::
int main(){
    bool run = (ret = somefunction()) == 1; //if the return of the function is 1
    run = (run || (ret == 2));              //or the return of the function is 2
    if (run){                               //execute this if block
        //conditional code
        if (ret == 1){
            //more conditional code
        }
    }
        //unconditional code
    if (run){
        //even more conditional code
    }
}
//:::::::::::::::::::::::::::::::::::::::
//  Option 1 End
//:::::::::::::::::::::::::::::::::::::::

写完之后,我认为这样做可能更有效:

//:::::::::::::::::::::::::::::::::::::::
//  Option 2 Start
//:::::::::::::::::::::::::::::::::::::::
int main(){
    bool run;
    if (run=(((ret = somefunction()) == 1)||ret == 2)){ //if the return of the function is 1 or 2 then execute this if block
        //conditional code
        if (ret == 1){
            //more conditional code
        }
    }
    //unconditional code
    if (run){
        //even more conditional code
    }
}
//:::::::::::::::::::::::::::::::::::::::
//  Option 2 End
//:::::::::::::::::::::::::::::::::::::::

我更喜欢第一种方法以提高可读性,因为它分为几行,而第二种方法在同一行中有两个赋值 (=) 和两个比较 (==)。 我想知道使用第二种方法是否更好(出于效率或可执行文件大小的原因),或者是否有比这两种方法更好的方法。

在任何人说它只会产生几乎无法估量的差异之前,这是一个巨大的循环,必须在 1/50 秒内运行数千次,所以我想尽可能多地节省时间。

【问题讨论】:

    标签: c++ if-statement


    【解决方案1】:

    性能不应该是您关心的问题:现代编译器通常足够聪明,可以在任何情况下优化代码。如果代码做的事情基本相同,结果将是相同的。

    因此,您应该更喜欢可读性更高(因此更易于维护)的变体。

    我会这样写:

    ret = somefunction();
    // I don't know what is the semantics of ret == 1, so let's imagine some
    bool operationIsPush = (ret == 1);
    bool operationIsOnTop = (ret == 2);
    
    if (operationIsPush || operationIsOnTop)
    {
        //conditional code
    }
    
    if (operationIsPush)
    {
        //more conditional code
    }
    
    //unconditional code
    
    if (operationIsPush || operationIsOnTop)
    {
        // ...
    }
    

    【讨论】:

    • 我明白你的意思,但不是必须先是“if IsPush”,然后是“if IsPush || IsOnTop”,然后是另一个“if IsPush”吗?谢谢。
    【解决方案2】:

    我相信这里的表现不会有任何差异。第一个原因是您的编译器可能会在每种情况下优化代码。第二个是你只是改变了操作发生的地方(比如“我做 A->B->C 或 A->C->B”),而不是操作的数量,所以它总是相同的计算量(1 个函数调用,几个== 等等)。

    但是考虑到这 (run=(((ret = somefunction()) == 1)||ret == 2)) 很难读。

    【讨论】:

      【解决方案3】:

      正确性比是否将两个分配一个布尔值的操作合二为一更重要(编译器可能无论如何都会这样做)。

      对于推送/弹出堆栈,您应该使用范围保护(原始文章here)。这将确保如果某些东西抛出了“无条件位”,而你永远无法确定,那么它仍然可以正常运行。否则你会得到一个有趣的惊喜(堆叠一个,或者溢出)。

      【讨论】:

        【解决方案4】:

        如果有一种情况可以将“if-else”拆分为不同的大循环,它会更快

        而不是

        loop {  if_1  {some work}    if_2 {some other work}   }
        

        你可以

        if_1 { loop {work }}    if_2 {loop{same work}}
        

        更极端的是,如果您可以拆分最内部的“if”句子,则可以有 10-20 个(取决于您的情况)运行 x2 x3 更快的不同的巨大循环(如果由于“if”而变得缓慢)

        【讨论】:

        • 这个问题是每个 if_1 在执行时必须有一个 if_2 执行,然后才能调用下一个 if_1 (在我的情况下)
        • 所以你说所有的 if 都是依赖的
        • 好吧,因为它在堆栈上,所以循环的每次迭代都必须是这样的:[if]push,操作,[if]pop,next iter...所以它不能很多的“[if]push”,然后是大量的操作,然后是大量的“[if] pop”
        • 嗯。您正在同时进行推送和检查“if”条件
        猜你喜欢
        • 2018-12-10
        • 1970-01-01
        • 1970-01-01
        • 2014-06-05
        • 1970-01-01
        • 1970-01-01
        • 2010-09-27
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多