开发者

Is putting a function within an if statement efficient? (C++)

开发者 https://www.devze.com 2022-12-08 08:05 出处:网络
I\'ve seen statements like this if(SomeBoolReturningFunc()) { //do some stuff //do some more stuff } and am wondering if putting a function in an if statement is efficient, or if there are cases wh

I've seen statements like this

if(SomeBoolReturningFunc())
{
    //do some stuff
    //do some more stuff
}

and am wondering if putting a function in an if statement is efficient, or if there are cases when it would be better to leave them separate, like this

bool AwesomeResult = SomeBoolReturningFunc();
if(AwesomeResult)
{
  开发者_如何学JAVA  //do some other, more important stuff
}

...?


I'm not sure what makes you think that assigning the result of the expression to a variable first would be more efficient than evaluating the expression itself, but it's never going to matter, so choose the option that enhances the readability of your code. If you really want to know, look at the output of your compiler and see if there is any difference. On the vast majority of systems out there this will likely result in identical machine code.


either way it should not matter. the basic idea is that the result will be stored in a temporary variable no matter what, whether you name it or not. Readability is more important nowadays because computers are normally so fast that small tweaks don't matter as much.


I've certainly seen if (f()) {blah;} produce more efficient code than bool r = f(); if (r) {blah;}, but that was many years ago on a 68000.

These days, I'd definitely pick the code that's simpler to debug. Your inefficiencies are far more likely to be your algorithm vs. the code your compiler generates.


as others have said, basically makes no real difference in performance, generally in C++ most performance gains at a pure code level (as opposed to algorithm) are made in loop unrolling.

also, avoiding branching altogether can give way more performance if the condition is in a loop.

for instance by having separate loops for each conditional case or by having a statements that inherently take into account the condition (perhaps by multiplying a term by 0 if its not wanted)

and then you can get more by unrolling that loop

templating your code can help a lot with this in a "semi" clean way.


There is also the possibility of

if (bool AwesomeResult = SomeBoolRetuningFunc()) { ... } 

:)

IMO, the kind of statements you have seen are clearer to read, and less error prone:

bool result = Foo();
if (result) {
    //some stuff
}
bool other_result = Bar();
if (result) { //should be other_result? Hopefully caught by "unused variable" warning...
    //more stuff
}


Both variants usually produce the same machine code and run exactly the same. Very rarely there will a performance difference and even in this cases it will unlikely be a bottleneck (which translates into don't bother prior to profiling).

The significant difference is in debugging and readability. With a temporary variable it's easier to debug. Without the variable the code is shorter and perhaps more readable.

If you want both easy to debug and easier to read code you should better declare the variable as const:

const bool AwesomeResult = SomeBoolReturningFunc(); 
if(AwesomeResult) 
{ 
    //do some other, more important stuff 
}

this way it's clearer that the variable is never assigned to again and there's no other logic behind its declaration.


Putting aside any debugging ease or readability problems, and as long as the function's returned value is not used again in the if-block; it seems to me that assigning the returned value to a variable only causes an extra use of the = operator and an extra bool variable stored in the stack space - I might speculate further that an extra variable in the stack space will cause latency in further stack accesses (not sure though).

The thing is, these are really minor problems and as long as the compiler has an optimization flag on, should cause no inefficiency. A different case I'd consider would be an embedded system - then again, how much damage could a single, 8-bit variable cause? (I have absolutely no knowledge concerning embedded systems, so maybe someone else could elaborate on this?)


The AwesomeResult version can be faster if SomeBoolReturningFunc() is fairly slow and you are able to use AwesomeResult more than once rather than calling SomeBoolReturningFunc() again.


Placing the function inside or outside the if-statement doesn't matter. There is no performance gain or loss. This is because the compiler will automatically create a place on the stack for the return value - whether or not you've explicitly defined a variable.


In the performance tuning I've done, this would only be thought about in the final stage of cycle-shaving after cleaning out a series of significant performance issues.


I seem to recall that one statement per line was the recommendation of the book Code Complete, where it was argued that such code is easier to understand. Make each statement do one and only one thing so that it is very easy to see very quickly at a glance what is happening in the code.

I personally like having the return types in variables to make them easier to inspect (or even change) in the debugger.

One answer stated that a difference was observed in generated code. I sincerely doubt that with an optimizing compiler.

A disadvantage, prior to C++11, for multiple lines is that you have to know the type of the return for the variable declaration. For example, if the return is changed from bool to int then depending on the types involved you could have a truncated value in the local variable (which could make the if malfunction). If compiling with C++11 enabled, this can be dealt with by using the auto keyword, as in:

auto AwesomeResult = SomeBoolReturningFunc() ;
if ( AwesomeResult )
{
    //do some other, more important stuff
}

Stroustrup's C++ 4th edition recommends putting the variable declaration in the if statement itself, as in:

if ( auto AwesomeResult = SomeBoolReturningFunc() )
{
    //do some other, more important stuff
}

His argument is that this limits the scope of the variable to the greatest extent possible. Whether or not that is more readable (or debuggable) is a judgement call.

0

精彩评论

暂无评论...
验证码 换一张
取 消