Should we prefer temporary variables over user defined variables in c++

梦想与她 提交于 2021-02-09 08:44:27

问题


Lets say there is a c++ function foo() which returns a boolean.

I call this functions to check the status of a property Or to get the result of the function call.

So what would be the best way to call this type of functions.

Method 1 :

bool flag = foo()
if (flag)
{
   // some code
}
else
{
   // else some code
}

Method 2:

if ( foo() )
{
   // some code
}
else
{
   // some code
}

My Question: Does using the temporary variable gives compiler opportunity to better optimize in general.


回答1:


First of all, let us remember than a compiler does not have the same view of the source code as we do: syntax does not matter to it, only semantics. As such, we could argue it has a rather symbolic view of the code.

Furthermore, when the optimizer comes into to play, it will apply analyses and transformations that will turn equivalent symbolic executions into the equivalent binary.

Therefore, what matters for optimization is semantics. There are 3 different syntactic forms that can be used for an if statement:

// with a temporary
if (make()) { ... } else { ... }

// with a variable already in scope
auto var = make();
if (var) { ... } else { ... }

// with a new variable
if (auto var = make()) { ... } else { ... }

The latter syntax is desugared to:

{ auto var = make(); if (var) { ... } else { ... } }

There is a semantic difference: the scope of those variables differ.

  • in the temporary case, its lifetime ends before the if or else block is executed
  • in the named variable case, its lifetime ends at the end of its scope, after the else thus

In general, the difference of lifetime should be negligible, semantically. There are some cases though where it might matter: if you need to access it or if the side effects need be properly sequenced.

There might be some effects on the emitted code:

  • for a built-in type: it is unlikely there will be any effect
  • for a POD type: it might not be optimized as clearly
  • for a non-POD type: the side-effects in the destructor (such as releasing memory) may inhibit optimizations

And which optimizations ?

Well, the primary optimization that could be applied here is stack reuse, whenever an object's lifetime has ended the compiler should be free to reuse its memory space for another object (see -fstack-reuse).

If the compiler cannot prove the object is no longer used, or must keep it alive because of side-effects in its destructors, then it might have to occupy more space on the stack for this object. As mentioned, it's unlikely this will occur (with optimizations turned on) when it comes to built-in types, but with a std::string unfortunately I would not be surprised.




回答2:


I normally go for the second unless I need to reuse the flag. It is true that in some occasions it may be useful for debug, but I don't like to pollute the code with temporary variables that the compiler is able to handle by itself.

A workaround would be to put all method one inside a block in order to free the flag after the if statement. Extra work for no result: I still go for method 2.




回答3:


The optimizer will generate the same thing. Aim for readable, understandable code. I usually prefer the first option, because it's easier to debug (you can see the value returned in the debugger).




回答4:


For primitive variables, there is no big difference. Both of them cause to generate same machine code due to optimizations. In the first case, the result is reusable also.

But, if the returned type is an object with a destructor. Then, a difference comes in. For first one the object will be destructed until exiting its scope (e.g. exiting the function in your case) and for second one, it will be destructed right after evaluation in if statement.




回答5:


I would prefer the first method with slight changes:

const bool flag = foo();  // const myclass &cref = foo_returning_object();
if (flag)
{
   // some code
}
else
{
   // else some code
}

In this case I can reuse the returned value if required. If my temporary is a const reference, it extends lifetime of the returned object and no overhead (constructur/destructor call) is imposed on my program.

Also as other post answers, it is easier to debug the returned value.




回答6:


It depends on the situation: if you use the value multiple times (andy only need to call foo once) or if you can give a very meaningful name to the variable, you should probably do it. If none of these are true, it's a matter of style/preference.

example (1):

bool flag = foo();
if (flag)   // used once
{
   // some code
}
else
{
   // else some code
}
bool other_flag = flag && bar(); // used twice: call bar (or not)
                                 // depending on flag

example (2):

bool foo_available = foo(); // "foo_available" is more explicit than "foo"
                            // and increases readability
// same code as yours, here


来源:https://stackoverflow.com/questions/23492258/should-we-prefer-temporary-variables-over-user-defined-variables-in-c

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!