Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can i = v.end() be optimized out of a for loop?

Tags:

c++

c++11

I saw something like this just now:

vector<int> x { 1, 2, 3, 4 };
for (auto i = x.begin(); i != x.end(); ++i)
{
  // do stuff
}

is it better to do this:

vector<int> x { 1, 2, 3, 4 };
for (auto i = x.begin(), end = x.end(); i != end; ++i)
{
  // do stuff
}

I guess I figured that the optimizer would take care of this. Am I wrong?

like image 946
Adrian Avatar asked Sep 20 '13 02:09

Adrian


2 Answers

Yes, the second version can be more optimal, so long as your container is never modified but the compiler cannot tell the container is never modified.

The "most optimal" looping structure can be found by examining the C++11 ranged-based for loop.

The code:

for( auto x : vec_expression ) {
  // body
}

is translated roughly into:

{
  auto&& __container = vec_expression;
  using std::begin; using std::end;
  auto&& __end = end(container)
  for( auto __it = begin(container); __it != __end; ++__it ) {
    auto x = *__it;
    {
      // body
    }
  }
}

where any variable starting with __ exists for exposition purposes only, and the using std::begin; using std::end; is magically removed from consideration within // body. (Remember, any variable containing __ is reserved for the compiler implementation).

If you have lambda support in your compiler, you can write your own version:

template<typename Container, typename Lambda>
void foreach( Container&& c, Lambda&& f ) {
  using std::begin; using std::end;
  auto&& e = end(c);
  for( auto it = begin(c); it != e; ++it ) {
    f(*it);
  }
}

which is used like this:

foreach( vec_expression, [&]( int x ) {
} );

it does not let you break, or return into the outer scope, but it is pretty close to C++11 ranged-based for.

If you lack both ranged-based for and lambdas, you could be a completely insane person and implement much of the above as a macro... Do the std::begin work using a helper function with perfect fowarding to avoid polluting the body of the function, mayhap.

like image 177
Yakk - Adam Nevraumont Avatar answered Nov 19 '22 01:11

Yakk - Adam Nevraumont


Most probably the optimizer will do the job for you.

By the way, why decltype(x.begin()) when there's auto for you?

for (auto i = x.begin(); i != x.end(); ++i)
{
  // do stuff
}

or even:

for (auto i : x)
{
  // do stuff
}

The latter is the range for: http://en.cppreference.com/w/cpp/language/range-for.

like image 5
vines Avatar answered Nov 19 '22 01:11

vines