Simple loop, which one I would get more performance and which one is recommended? defining a variable inside a loop or outside of it?

Go To StackoverFlow.com

1

Variable outside of the loop

int number = 0;
for(int i = 0; i < 10000; i++){
     number = 3 * i;
     printf("%d",number);
}

or Variable inside of the loop

for(int i = 0; i < 10000; i++){
     int number = 3 * i;
     printf("%d",number);
}

Which one is recommended and which one is better in performance?

Edit:

This is just an example to exhibit what I mean, All I wanna know is if defining a variable inside a loop and outside a loop means the same thing , or there's a difference.

2012-04-03 22:31
by Grego
Pick the one that's prettier - Mysticial 2012-04-03 22:33
Those two snippets will likely end up being processed into 100% identical assembly - Corbin 2012-04-03 22:33
That's what I've been going for, but when dealing with a lot of data, probably there's one that outperforms the other - Grego 2012-04-03 22:34
Do you use number outside the loop? This will give you your answer - Jesse Good 2012-04-03 22:34
You could always either look at the assembly or profile the code. In a case as trivial as this, the compiler will optimize out the variable (though of course a register will still be used). In more complex cases, I would imagine the compiler would optimize it fairly well too, but of course there would be no guarantees - Corbin 2012-04-03 22:35
Possible duplicate: http://stackoverflow.com/questions/982963/is-there-any-overhead-to-declaring-a-variable-within-a-loop- - K Mehta 2012-04-03 22:38
If number is a user-defined object, then yes it might matter.. - Mysticial 2012-04-03 22:40
@KshitijMehta: Different languages and different constructs, I don't see how that would be a duplicate. Not that the question makes any sense - David Rodríguez - dribeas 2012-04-03 22:44
@DavidRodríguez-dribeas I edited the link after I realized that I had linked to the wrong question. Guess you were looking at the unedited version - K Mehta 2012-04-03 22:45
@Jesse I think any better compiler would optimize it out (multiple loops embedded could break my assumption though) - pruzinat 2012-04-03 23:01
Hey, if my answer (or anyone else's) fits what you're looking for, please click accept so we get a green checkmark and the +15 rep it entails! It's a win-win because it gives you stuff too! Thanks - std''OrgnlDave 2012-04-07 23:55


5

Time to learn something early: any optimization you could make on something like this will be irrelevant in the face of printf.

Printf will be very, very slow. You could quintuple the math and get no measurable speed decrease. It's just the nature of printing to the terminal.

As for your edited question, there is no difference defining it in the loop or out. Imagine that

for (i = 0; i < 500; i++) {
  int a = i * 3;
}

is just the same as

int forloop::a; // This doesn't work, the idea is to show it just changes the scope
for (i = 0; i < 500; i++) {
  a = i * 3;
}

They will produce identical code, unless you start needing to use that variable outside of the loop it is defined in, because it is defined in the local scope of the loop. So...more like this:

int forloop::a;    // Still not valid code, just trying to show an explanation
namespace forloop {
for (i = 0; i < 500; i++) {
  a = i * 3;
}
} // namespace forloop

If this is unclear please let me know I'll go into more detail or explain differently.

2012-04-03 22:37
by std''OrgnlDave
thanks for the assistance : - rdlowrey 2012-05-12 06:44


2

Do not bother you with performance at first: make it safe before everything.

I would just quote Scott Meyers (Effective C++) for your concern: "Postpone declarations as far as you can". Thus, the second pattern is safer.

Example:

int j = 0;
for(int i = 0; i < 10000; i++){
    j = 3 * i;
    printf("%d",j);
}
...
// Use of j out of control!!!
int k = j * 5;

Now with the second pattern:

for(int i = 0; i < 10000; i++){
    int j = 3 * i;
    printf("%d",j);
}
...
// j not declared at this point.
// You get informed of the mistake at compile time, which is far much better.
int k = j * 5; 
2012-04-03 22:53
by aroyer
You know, that has its ups and downs. Unfortunately you can declare duplicate variable names inside the loop. So you can have a for loop with int j in it, but there's already an int j in the function. You can get confused about what j you're using. I think it really, really depends on context - std''OrgnlDave 2012-04-03 22:58
By the way some older versions of gcc would not complain at all (program would still work as "expected" though). Nowadays it should produce at least warning (or even error), I think it was burried in standard somewhere - pruzinat 2012-04-03 23:03
@AoeAoe I was completely surprised. I discovered this "the hard way" (meaning >15 minutes of debugging) and was completely surprised the compiler didn't warn me about the situation. I believe that was MSVC2k - std''OrgnlDave 2012-04-03 23:05
@OrgnlDave: If you have conflicts with variables names like j then you should pick more meaningful variable names - Blastfurnace 2012-04-04 00:00
@Blastfurnace Yes indeed, we should all pick meaningful names. Thankfully for me I usually do. Unfortunately it was a relatively meaningful name, I don't remember it, but it was something like event_count or something - std''OrgnlDave 2012-04-04 00:22
By postponing the deceleration, you help compiler to optimize your code. Moreover, I would help you to avoid bugs and better debug - iampat 2012-04-04 02:41
@Blastfurnace You're completely right! Meaningful variable names is one of the very first things to do to make the code safer. I just used a dummy variable name here in order to illustrate a possible risk - aroyer 2012-04-04 20:38
@iampat postponing your variable declarations is great as long as they are primitives. your program will choke and die if you make it into the wrong type of class - std''OrgnlDave 2012-04-07 23:53


2

You do have a C++ tag, and you mention "declaring a string" in the question. Therefore there might be a performance difference (and yes, the printf could swamp it). Declaring a non-simple variable means calling a constructor, which might mean a non-trivial amount of work. In that case, declaring it inside of the loop could be hiding significant work in what appears to be an innocent declaration.

In general, the answer is that if you really care about performance - and treating the sample code as only an example of the difference between two places to declare a variable - then for non-simple variables, it is better to declare it outside the loop, unless the semantics require a fresh version of a temporary at each iteration.

There are likely many other places first to look at if performance is an issue, but one consideration is always moving loop invariants out of loops, especially if it is much easier for you to tell that it is invariant than for the compiler. And what looks like a declaration, can, in C++, fall into that category.

If, for (silly) example, you have

int k = 43;
for ( int i = 0; i < N; ++i )
    {
    int j = 17 + k; // k was previously defined outside the loop, but doesn't change in it
    l = j * j; // l was also declared outside the loop
    }

any good optimizing compiler can recognize that k is constant, and that j is always assigned 60, and l is assigned 3600 N times, and the loop can simply be removed and replaced with a single assignment to l. Here k and j are both loop invariants.

But a not-quite-so-good compiler might miss even one link in that chain, and wind up creating the loop.

It gets harder for the compiler to figure things out when you have

 Foo k( 43 );  // a class that takes an int argument to its constructor
 for( int i = 0; i < N; ++i )
    {
    Bar j( k ); // a Bar takes an int argument, adds 17 and stores it.
    l = j.squared();
    }

Same invariants. Not as easy to detect without looking inside the workings of bar; and if the constructor and squared method aren't inline, we've just made it slower.

2012-04-03 23:05
by DRVic
Good point, temporaries can be pains. But they're a bit more subtle than you're painting them, for instance a = i * 3 can still create a temporary of type a depending on how the class is structured even if it's declared outside. But it's a good point that I missed. I guess I was only thinking in C (even though I used namespace/scope in my explanation, haha). I think a bit more exposition on what a loop invariant is would be helpful for future readers, though - std''OrgnlDave 2012-04-03 23:10
Done. Perhaps overboard - DRVic 2012-04-03 23:22
I don't think so. I think the answers are complementary. It would only be overboard if this didn't have a 'c++' tag. I suggested you add it because I can't tell you how many times I've come across an SO question or random forum post and somebody answered just short of enough info... or even worse in forums "nevermind I fixed it" and you never read how... I believe it's sort of our responsibility to inform people who may google this and find it 5 years from now. obligatory XKCD http://xkcd.com/979 - std''OrgnlDave 2012-04-03 23:33


0

In this case, printf("%d", i * 3) would be better than defining the variable at all.

2012-04-03 22:34
by Brendon Cheves
Performance wise, I would be utterly surprised if it mattered at al - David Rodríguez - dribeas 2012-04-03 22:41
And the best looking - Whymarrh 2012-04-03 23:09


0

To answer your question and not nitpicking:

The difference between the 2 variants is, that you are declaring your variable number in different "variable environments" - by which I mean that the scope changes. A variable environment is given by your curly braces { ... }. Everytime you open a new curly brace like this { ... { ... } ... }, you declare a new variable environment inside the old one, which means, that if you declare numbers like so:

{ ... { int numbers; ... } ... }

this variable will only be visible or existent in the innermost environment. So

{ ... { int numbers; ... } ... do_something(numbers); ... }

will give a compiler error.

And to your concerns about performance: Neither variant is better performing. Most, if not all compilers will give the same assembly.

2012-04-03 22:50
by Anthales
Is the term "variable environment" a functional programming concept? I haven't heard this term used in a C++ context - Jesse Good 2012-04-03 23:00
@Jesse Nonono, this has nothing to do with functional programming, it's just the way the language allows to declare variables locally, instead of having one giant blob of millions of variables, which would constantly result in naming collisions. Also I don't even now if the term "variable environment" actually exists in the C++ standard, I just called it that - Anthales 2012-04-03 23:02
I was just more used to using the term scope which is why I asked - Jesse Good 2012-04-03 23:06
Ah, I forgot that term :) Yeah, maybe I should edit my post - Anthales 2012-04-03 23:09
Ads