Recycling variables and performance

Started by
31 comments, last by mrbastard 12 years, 10 months ago
Hello everyone,

My colleague and I discussed whether it is actually faster to pre-declare and recycle as many function variables as possible.
I've been taught (and so i practice), to declare and initialize variables only when i need to use them. Preferably in a scope not covering more
than where it's potentially used. So my colleague asked if i would redeclare for-loop variable i rather than declaring it once, just because it's a prettier coding style:

for(unsigned i = 0; 10 != i; ++i)
{
}

for(unsigned i = 0; 10 != i; ++i)
{
}

for(unsigned i = 0; 10 != i; ++i)
{
}

As opposed to:


unsigned i;

for(i = 0; 10 != i; ++i)
{
}

for(i = 0; 10 != i; ++i)
{
}

for(i = 0; 10 != i; ++i)
{
}


Comments on the whole predeclare then use vs late declaration/initialization are also welcome, although I'd prefer to tell him that at least,
the triple-declaration results in at least as fast code.
Advertisement
In the above case, there's absolutely no difference in performance. The second one is worse stylistically IMHO, because the variable [font="Courier New"]i[/font] which logically only belongs inside the scope of the loop has 'leaked' outside of that scope.

This is because unsigned int is a primitive type -- creating and destroying primitive types basically has no cost; they have no constructor or destructor to call (in most cases).

http://www.parashift...nsic-types.html
http://stackoverflow...-pod-types-in-c
http://en.wikipedia...._data_structure

[Edit]
If you're dealing with objects that have expensive constructors/destructors, then things are different.
E.g. instead of making an expensive object repeatedly:for( ... )
{
std::vector<int> vec;//constructor
//..
//destructor
}
...sometimes you can make this object once, and reuse it:{
std::vector<int> vec;//constructor
for( ... )
{
//.. vec.clear();//reset it to a default state
}
//destructor
}
The main thing for me is correctness. Re-using variables for different purposes can cause bugs. I would always urge caution - consider whether premature optimisation is motivating such a change. If profiling indicates problems, then that is a different matter.

In the case you gave, performance shouldn't be a concern, "i" will probably be in a register.
1. The compiler will do this for you anyway if it thinks it's safe to happen.

2. You almost certainly do not have the sort of performance problems that this is likely to help with.
When writing code for some of the embedded devices I've worked on, their compilers are a fair way behind and don't respect the for loop variable scoping rules, thue you're forced to do it the second way. Over a decade ago when working on a software 3D engine in a tight spot (rendering loop) it was significantly faster to reuse a couple of variables because it helped the compiler out with register allocation. With more recent compilers I've found that I was able to make that same code readable again with no loss of performance. So nowdays you don't have to sacrifice readability; since you get nothing good from doing so.

I must say though that I dislike your for loop condition. i < 10 always, for maximum readability. Writing it the other way around has always been a ridiculous idea. If you can remember to force yourself to reverse the condition, reducing readability, then you can instead remember to force yourself to use == instead of =. In this case though, it doesn't even apply. Also, compilers detect that sort of mistake for you, so there's really no excuse for it.
"In order to understand recursion, you must first understand recursion."
My website dedicated to sorting algorithms

I must say though that I dislike your for loop condition. i < 10 always, for maximum readability. Writing it the other way around has always been a ridiculous idea. If you can remember to force yourself to reverse the condition, reducing readability, then you can instead remember to force yourself to use == instead of =. In this case though, it doesn't even apply. Also, compilers detect that sort of mistake for you, so there's really no excuse for it.

@iMalc: Thanks for your response! Yes, you are right; the reason I write it like that is, that I'll get a parser error if i accidentally type =, rather than == or !=, as i always leave a const expression on the left-hand side. I've been practicing this because I can be sure that the condition doesn't assign while sacrificing little or no readability.

It's nice to get some good input on the reverse thing, though, you're seeing exactly why I'm doing it, and you're right as far as the "if I can remember to reverse the condition, I can remember == also". I will take that into consideration when i write my next for-loop. ;)

One might of course argue that we empathize that the loop should take place 10 times, and therefore it's actually preferable to have it earlier on the line, even for readability.
Also I think you should meet a condition with a clearly defined == or !=, as you'll be able to determine exactly where the for-variable should stop unless you use floats. If one cannot do that, and tends to use > or < when counting integers, I think one should reconsider the for-loop entirely.

However it's great to get some proper input on the semantics, it seems being taught by old-school developers have both advantages and disadvantages. :-)

It's good to know that the issues with the early declarations have been dealt with, and my lessons as well as passing on of the late initialization -practice have been correct. Thanks Rip-off and Hodgman for supplying details.


http://www.parashift...nsic-types.html

@Hodgman: I read that. Makes good sense, as always! :) (I've ordered that book from the parashift.com -site. I always think his writing style in there is great, and hope to find it in the book, too!)

10 != i


It burns!!!

One might of course argue that we empathize that the loop should take place 10 times, and therefore it's actually preferable to have it earlier on the line, even for readability.
Also I think you should meet a condition with a clearly defined == or !=, as you'll be able to determine exactly where the for-variable should stop unless you use floats. If one cannot do that, and tends to use > or < when counting integers, I think one should reconsider the for-loop entirely.


I am not sure where you learned this, but it runs quite contrary to what is considered good style by the majority of authorities on the matter, and is more error prone than the alternatives (authorities in this instance being style guides such as Code Complete and other sources such as Bjarne's own works). Since the for loop counter do more than simple incrementation, you run the risk of creating an infinite loop with the == != syntax should your termination condition be incorrect, whereas a < or > will generally terminate the loop. Also, as you mentioned, floats. Also, for loops typically operate over simple mathematical sequences (0, 1, 2, 3, 4 or 0, 3, 6, 9 etc) and sequences are usually defined as a range, such as "all positive integers less than X" rather than "all positive integers not equal to 10" (notice how one of these actually does not express the sequence we intend to use for our for loop).

[quote name='SuperVGA' timestamp='1308203413' post='4823948']
One might of course argue that we empathize that the loop should take place 10 times, and therefore it's actually preferable to have it earlier on the line, even for readability.
Also I think you should meet a condition with a clearly defined == or !=, as you'll be able to determine exactly where the for-variable should stop unless you use floats. If one cannot do that, and tends to use > or < when counting integers, I think one should reconsider the for-loop entirely.


I am not sure where you learned this, but it runs quite contrary to what is considered good style by the majority of authorities on the matter, and is more error prone than the alternatives (authorities in this instance being style guides such as Code Complete and other sources such as Bjarne's own works). Since the for loop counter do more than simple incrementation, you run the risk of creating an infinite loop with the == != syntax should your termination condition be incorrect, whereas a < or > will generally terminate the loop. Also, as you mentioned, floats. Also, for loops typically operate over simple mathematical sequences (0, 1, 2, 3, 4 or 0, 3, 6, 9 etc) and sequences are usually defined as a range, such as "all positive integers less than X" rather than "all positive integers not equal to 10" (notice how one of these actually does not express the sequence we intend to use for our for loop).
[/quote]

Actually I was taught so by a former colleague of mine who is a c++ guru and has contributed to the works of Stroustrup. I'll try to defend it as I practice it and as he originally argued well for its use. When you work with iterators for instance, you define range as a place to start and a place to end. I'm not doing anything differently by telling at exactly which value to stop at.

Are you not aware of when to stop counting? If your code is broken, and you "accidentally" skip past the value to end at, you have much bigger issues than putting a const before a variable: you cannot defend how the code will behave.

If I break something, I will instantly know because i write so that problems will show themselves at compile time.

You mention written works arguing against this practice, (error prone and against good coding style) -could you help me to the source for it? I cannot find it.

Happy for your input although this thread has somewhat strayed from the original purpose. ;-)
10 != i

I don't do it this way, but I don't really see anything wrong with it. It's the same thing you do with iterators.

std::vector<int> vec;
for (std::vector<int>::iterator i=vec.begin(); i != vec.end(); i++)
{
....
}


It's the same thing, no?

This topic is closed to new replies.

Advertisement