Is there a difference, in terms of performance, between the two loops below? (myvec is type std::vector<int> .)

std::vector<int>::const_iterator pos;
for (int i = 0; i < N; i++) {
    pos = myvec.begin();
    // do something with pos
}
for (int i = 0; i < N; i++) {
    std::vector<int>::const_iterator pos = myvec.begin();
    // do something with pos
}

Recommended Answers

All 4 Replies

in second you create std::vector<int>::const_iterator pos every time when you loop and then change value :) in first when loop it only change value

>Is there a difference, in terms of performance, between the two loops below?
It depends on your compiler. There are tons of factors that come into play, such as how your compiler manages stack space, whether the underlying type of const_iterator is a simple pointer or an object, how temporary objects are managed, whether object creation/destruction outweighs copy construction/assignment or the creation/destruction is a bottleneck, etc...

The best answer is that if it matters you'll notice a problem during performance profiling, and until then you should limit the scope of variables as much as possible. Thus, the second example is preferred.

>Is there a difference, in terms of performance, between the two loops below?
It depends on your compiler. There are tons of factors that come into play, such as how your compiler manages stack space, whether the underlying type of const_iterator is a simple pointer or an object, how temporary objects are managed, whether object creation/destruction outweighs copy construction/assignment or the creation/destruction is a bottleneck, etc...

The best answer is that if it matters you'll notice a problem during performance profiling, and until then you should limit the scope of variables as much as possible. Thus, the second example is preferred.

Narue could you elaborate more on this... It seems like an interesting subject! Being ignorant in the beggining i would agree ivailosp , but you seem to have a point.

Also to limit the scope of the variable and not create it every time we loop, couldn't we write:

{
  std::vector<int>::const_iterator pos;
  for (int i = 0; i < N; i++) 
  {
     pos = myvec.begin();
     // do something with pos
  }
}

thanks in advance,
-nicolas

>Narue could you elaborate more on this...
People usually have an easier time understanding the rough idea of memory when I explain it using assembly. When a "function" is called, local variables are typically allocated by adjusting the stack pointer to make a big enough gap to hold values for all of the variables:

function:
  add sp, localsize ; Make a hole

  ; Use the locals

  sub sp, localsize ; Close the hole
  ret

That's the general idea behind figuring that the loop doesn't actually reallocate memory with each iteration. In that case, assuming that const_iterator is an class type rather than a built-in type, you can make the examples more accurate like so:

std::vector<int>::const_iterator pos;
for (int i = 0; i < N; i++) {
  pos = myvec.begin();
  // do something with pos
}
{
  std::vector<int>::const_iterator pos;
  for (int i = 0; i < N; i++) {
    pos.const_iterator ( myvec.begin() );
    // do something with pos
    pos.~const_iterator();
  }
}

That seems like a big difference until you consider that the temporaries for myvec.begin() are probably going to be handled identically and that copy construction and assignment are similar enough not to be significantly different in their performance characteristics. Thus the only real difference is that the destructor is called for pos on every iteration in the second example. Unless the destructor is a heavy hitter when it comes to performance (note that the memory isn't being released at this point), the two examples won't much matter except for the scope issue.

That's the complicated situation, where const_iterator is a class type. If const_iterator is just a pointer, all of the construction and temporary crap doesn't even enter into the picture, and the two examples look like this (when you take the centralization of stack allocation into account):

std::vector<int>::const_iterator pos;
for (int i = 0; i < N; i++) {
  pos = myvec.begin();
  // do something with pos
}
{
  std::vector<int>::const_iterator pos;
  for (int i = 0; i < N; i++) {
    pos = myvec.begin();
    // do something with pos
  }
}

Now there isn't any difference at all except for scope. And all of this is a direct analysis of the code without even considering compiler optimizations. When optimizations enter the picture, even basic logic can be tossed out the window.

However, guidelines exist so you don't have to be intimate with your compiler and to encourage good, portable code. And the guideline is to limit the scope of your variables as much as possible, and only optimize if performance becomes an issue and the scope of your variables turns out to be the bottleneck during profiling.

>It seems like an interesting subject!
It's very interesting, and it gets more interesting as you delve deeper and deeper. :)

>Also to limit the scope of the variable and not create it every time we loop, couldn't we write
Yup, and that's exactly how you'd create a C++ style for loop in C89:

/*
  for ( int i = 0; i < N; i++ )
    ;
*/
{
  int i;

  for ( i = 0; i < N; i++ )
    ;
}
commented: When's the book coming out? :icon_razz: +15
commented: Interesting analysis. +2
commented: Thanks for the insight! :) +2
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.