Is There Any Overhead to Declaring a Variable Within a Loop - C++

Is there any overhead to declaring a variable within a loop? (C++)

Stack space for local variables is usually allocated in function scope. So no stack pointer adjustment happens inside the loop, just assigning 4 to var. Therefore these two snippets have the same overhead.

Does It Matter If I Declare A Variable Inside A Loop?

Yes, it does matter. In second case

int count=0;
while(count<10)
int a=0;

a can't be referenced out side of while loop. It has block scope; the portion of the program text in which the variable can be referenced.

Another thing that Jonathan Leffler pointed out in his answer is both of these loops are infinite loop. And second, the most important second snippet would not compile without {} (in C) because a variable definition/declaration is not a statement and cannot appear as the body of a loop.

 int count  =0;
while(count++ < 10)
{
int a=0;
}

Is it efficient to declare a variable in a loop?

I believe the variables will only be created once, although I do not care and I don't believe you should either.

This is likely an example of pre-optimization (or unnecessary optimization) on your part; the potential inefficiency created by declaring variables within a loop is incredibly small and "optimizing" your code by declaring variables in different locations will have a negligible impact on the overall runtime and memory usage of your program.

Consider spending time optimizing your algorithms and finding efficient data structures, as this will likely be a much better use of your time.

Does declaring a variable inside a loop body have any disadvantages?

Conceptually that variable is constructed and destructed on each iteration.

But does it affect performance? Well, you can check your case right here. Delete int on line 7 to switch between the loop-local and function-local variables.

Conclusion: no difference whatsoever. The assembly is the same!

So, just use what makes sense in your code. If you need one object per iteration, make one object per. The optimizer is smarter than you think. If that wasn't enough, you'd come back to it with profiling data and careful tweaking, not broad guidelines.

Declaring variables inside loops, good practice or bad practice?

This is excellent practice.

By creating variables inside loops, you ensure their scope is restricted to inside the loop. It cannot be referenced nor called outside of the loop.

This way:

  • If the name of the variable is a bit "generic" (like "i"), there is no risk to mix it with another variable of same name somewhere later in your code (can also be mitigated using the -Wshadow warning instruction on GCC)

  • The compiler knows that the variable scope is limited to inside the loop, and therefore will issue a proper error message if the variable is by mistake referenced elsewhere.

  • Last but not least, some dedicated optimization can be performed more efficiently by the compiler (most importantly register allocation), since it knows that the variable cannot be used outside of the loop. For example, no need to store the result for later re-use.

In short, you are right to do it.

Note however that the variable is not supposed to retain its value between each loop. In such case, you may need to initialize it every time. You can also create a larger block, encompassing the loop, whose sole purpose is to declare variables which must retain their value from one loop to another. This typically includes the loop counter itself.

{
int i, retainValue;
for (i=0; i<N; i++)
{
int tmpValue;
/* tmpValue is uninitialized */
/* retainValue still has its previous value from previous loop */

/* Do some stuff here */
}
/* Here, retainValue is still valid; tmpValue no longer */
}

For question #2:
The variable is allocated once, when the function is called. In fact, from an allocation perspective, it is (nearly) the same as declaring the variable at the beginning of the function. The only difference is the scope: the variable cannot be used outside of the loop. It may even be possible that the variable is not allocated, just re-using some free slot (from other variable whose scope has ended).

With restricted and more precise scope come more accurate optimizations. But more importantly, it makes your code safer, with less states (i.e. variables) to worry about when reading other parts of the code.

This is true even outside of an if(){...} block. Typically, instead of :

    int result;
(...)
result = f1();
if (result) then { (...) }
(...)
result = f2();
if (result) then { (...) }

it's safer to write :

    (...)
{
int const result = f1();
if (result) then { (...) }
}
(...)
{
int const result = f2();
if (result) then { (...) }
}

The difference may seem minor, especially on such a small example.
But on a larger code base, it will help : now there is no risk to transport some result value from f1() to f2() block. Each result is strictly limited to its own scope, making its role more accurate. From a reviewer perspective, it's much nicer, since he has less long range state variables to worry about and track.

Even the compiler will help better : assuming that, in the future, after some erroneous change of code, result is not properly initialized with f2(). The second version will simply refuse to work, stating a clear error message at compile time (way better than run time). The first version will not spot anything, the result of f1() will simply be tested a second time, being confused for the result of f2().

Complementary information

The open-source tool CppCheck (a static analysis tool for C/C++ code) provides some excellent hints regarding optimal scope of variables.

In response to comment on allocation:
The above rule is true in C, but might not be for some C++ classes.

For standard types and structures, the size of variable is known at compilation time. There is no such thing as "construction" in C, so the space for the variable will simply be allocated into the stack (without any initialization), when the function is called. That's why there is a "zero" cost when declaring the variable inside a loop.

However, for C++ classes, there is this constructor thing which I know much less about. I guess allocation is probably not going to be the issue, since the compiler shall be clever enough to reuse the same space, but the initialization is likely to take place at each loop iteration.

Loop performance for local variable

In general there will be the overhead of running the constructor/deconstructor of your object per loop iteration, if it isn't plain old data. In case of string: allocating and deallocating str's internal buffer. This only impacts performance if findStr and processStr are both highly performant too.

What is the good practice to declare loop variables?

You said:

the variable i is declared on every iteration of the loop! These re-declarations consume more processing power and re-allocation of memory again and again

This is an invalid assumption on your part. The C compiler will calculate the total memory the function needs and allocate for that usage up front. For local variables, that allocation is actually just a shift of a pointer.

To illustrate, if I have a function:

void a_function () {
extern int x, n1, n2;

while (--n1) {
int i;
scanf("%d", &i);
x += i;
}

while (--n2) {
int i, j;
scanf("%d %d", &i, &j);
x += i + j;
}
}

The compiler will allocate space for 2 integers on entry into the function (or none, if it decides it can do everything in registers).

Should variable declarations always be placed outside of a loop?

No, it wouldn't be more efficient. However, I'd rewrite it this way which happens to declare it outside the loop anyway:

byte[] buffer = new byte[32768];
int read;
while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
{
output.Write(buffer, 0, read);
}

I'm not generally a fan of using side-effects in conditions, but effectively the Read method is giving you two bits of data: whether or not you've reached the end of the stream, and how much you've read. The while loop is now saying, "While we've managed to read some data... copy it."

It's a little bit like using int.TryParse:

if (int.TryParse(text, out value))
{
// Use value
}

Again you're using a side-effect of calling the method in the condition. As I say, I don't make a habit out of doing this except for this particular pattern, when you're dealing with a method returning two bits of data.

The same thing comes up reading lines from a TextReader:

string line;
while ((line = reader.ReadLine()) != null)
{
...
}

To go back to your original question: if a variable is going to be initialized in every iteration of a loop and it's only used within the body of the loop, I'd almost always declare it within the loop. One minor exception here is if the variable is being captured by an anonymous function - at that point it will make a difference in behaviour, and I'd pick whichever form gave me the desired behaviour... but that's almost always the "declare inside" form anyway.

EDIT: When it comes to scoping, the code above does indeed leave the variable in a larger scope than it needs to be... but I believe it makes the loop clearer. You can always address this by introducing a new scope if you care to:

{
int read;
while (...)
{
}
}

Defining variable outside of a loop

I expect all modern compilers to produce identical code in both cases.

You might be surprised to know that with most compilers there is absolutely no difference whatsoever in the amount of overhead between either case.

In brief, these kinds of variables are instantiated on the stack, and a compiler, for each function, computes the maximum amount of stack needed to instantiate all local variables inside the function, and allocate the required stack space at the function's entry point.

Of course, if instead of a simple int you have some class with a non-trivial amount of complexity in its constructor, then it would certainly make a lot of difference, in several ways. But for a simple int like this, absolutely nothing.

Objective-C Declaring Variables Within Loop -- Performance

The answer is: it depends.

For variables in loops, moving them out of the loop might improve performance of the loop, but now you've changed the scope and effected performance in another way. Which is better is definitely going to be situation-based.

But, as far as I'm concerned, a variable with a scope any wider than necessary is bad practice. Variables with unnecessarily wide scope and lead to user error. The amount of performance improvement you might get here is not worth ANY amount of debugging that could've been avoided with a narrower variable scope.

As for calling methods in loop conditions, again, this depends.

I'm quite certain that the length method of NSString is quite optimized. The length of a string is not analyzed every time length is called, and especially not so for NSString (as opposed to NSMutableString. If we're talking about an immutable string, calling length is simply returning an NSInteger value stored within the class and performance will be fine.

If, however, we're talking about an immutable string, we need to call length every time if it's important that we're only within the length of the string.

It's a mutable string. Even if this loop doesn't modify the string, it can be modified else where by anyone that has a reference to it. If you're concerned about performance, make an immutable copy of the string and use that immutable copy in the loop.



[myString length]

According to this answer, for both mutable and immutable versions, there is a variable within the class that stores the string's length. For immutable strings, this is calculated when the string is created and never changed. For mutable strings, this variable is calculated and set each time the string changes. At the end of the day, when you call string, it's purely returning the value of an internally stored int value in the class and will not be any slower than storing this length in a separate variable before the loop and comparing against this.



Related Topics



Leave a reply



Submit