Should I bring temporary variable declarations out of loops in C and C++?
Here is what I mean, suppose I have code like:
for (int i = 0; i < 1000; i++) {
char* ptr = something;
/*
... use ptr here
*/
}
It seems that char* ptr
gets allocated every time in the loop, making it ineffective?
开发者_StackOverflowIs it more effective to write this?
char* ptr = something;
for (int i = 0; i < 1000; i++) {
/*
... use ptr here
*/
}
Please comment on this interesting problem. Thank you!
Thanks, Boda Cydo.
It can make a performance difference, but many optimizing compilers undertake this optimization for you, if appropriate. This is called "loop-invariant code motion".
I'm of the school that thinks it's better to limit the scope of variable names as much as possible; if ptr
isn't meant to be referenced outside of the loop, then it should not be declared outside of the loop.
However, if something
turns out to be an expensive operation AND it's invariant (i.e., it doesn't depend on i
) AND it's preventing your code from meeting a hard performance requirement, then yes, you should move the declaration outside of the loop.
This is unspeakably ugly, but you can do something like this:
do
{
char *ptr = something;
for (int i = 0; i < 1000; i++)
{
/* use ptr here */
}
} while (0);
You're still limiting the scope of ptr
, but you're no longer assigning it on every loop iteration.
The way that code gets translated really depends on your compiler and the optimizations it performs. The compiler might perform a "dumb" translation and allocate every loop, or it might place the allocation outside the loop for you in it's optimization phase. To be safe, I would place the declaration outside the loop. As with anything, you could test out both and see how long each loop takes to see if there is a difference.
You have to profile and see for yourself. Check out this question (and the accepted answer) of mine as a reference. As jalf says, it's just a rule of thumb to expect it to be optimized away (and it's probably correct for POD types) but you'll need to back it up with profiling.
As a matter of personal convention in 'C' programs, I like to put variable declarations at the top of the function, top of the file or in a common .h file. If I start to bury declarations within the code it could potentially be confusing and easy to lose track of variable scope, resulting in unwanted consequences.
For built-in types such as the char*
in your example, there isn't much difference. The second form is usable after the loop exits, and only evaluates the initializer once. But as John says, most compilers will precalculate the initialization anyway.
There's an obvious difference if ptr
gets re-assigned inside the loop (and if you don't reassign it, you should make it char* const ptr
), in that the value will be kept from the previous iteration instead of reset.
Finally, non-POD types would have their constructor and destructor run for every loop iteration.
精彩评论