Range-based loop optimization

J

Juha Nieminen

Assume that I have something along the lines of:

//----------------------------------------------------
struct Something
{
std::vector<SomethingElse> aBigVector;
std::set<FooBar> aBigSet;
};
//----------------------------------------------------

and then I inadvertently do something like this:

//----------------------------------------------------
std::vector<Something> container;
populate(container);

for(auto element : container)
// code that does not modify 'element'
//----------------------------------------------------

What I *should* have done is, of course, this:

//----------------------------------------------------
for(const auto& element : container)
...
//----------------------------------------------------

Or even just:

//----------------------------------------------------
for(auto& element : container)
...
//----------------------------------------------------

If, however, I mistakenly do it without a reference, will the compiler
be able to optimize the copying of the large elements if it sees that
they are not modified in the loop body?

If the compiler is unable to optimize the copying away, I'm thinking
that the range-based loop is way too easy to use in an inefficient manner
by mistake. This is not a very good thing.
 
M

Marc

Juha said:
Assume that I have something along the lines of:

//----------------------------------------------------
struct Something
{
std::vector<SomethingElse> aBigVector;
std::set<FooBar> aBigSet;
};
//----------------------------------------------------

and then I inadvertently do something like this:

//----------------------------------------------------
std::vector<Something> container;
populate(container);

for(auto element : container)
// code that does not modify 'element'
//----------------------------------------------------

What I *should* have done is, of course, this:

//----------------------------------------------------
for(const auto& element : container)
...
//----------------------------------------------------

Or even just:

//----------------------------------------------------
for(auto& element : container)
...
//----------------------------------------------------

If, however, I mistakenly do it without a reference, will the compiler
be able to optimize the copying of the large elements if it sees that
they are not modified in the loop body?

I don't think it is allowed to. Copy elision happens in a very limited
set of explicitly listed cases, and they are all about omitting a
temporary when creating a new object, which isn't the case here.

On the other hand, if your copy constructor has no side effect and is
simple enough for the compiler to understand, it will optimize and
remove most of the actions of copying. It depends what is in the body
of your for loop (if it is empty...), but it would require a very
clever compiler for a std::set to fall into this category. For
std::vector<POD>, it seems almost within reach of current compilers.
 
W

woodbrian77

Assume that I have something along the lines of:

//----------------------------------------------------
struct Something
{
std::vector<SomethingElse> aBigVector;
std::set<FooBar> aBigSet;
};
//----------------------------------------------------

and then I inadvertently do something like this:

//----------------------------------------------------
std::vector<Something> container;
populate(container);

for(auto element : container)
// code that does not modify 'element'
//----------------------------------------------------

What I *should* have done is, of course, this:

//----------------------------------------------------
for(const auto& element : container)
...
//----------------------------------------------------

Or even just:

//----------------------------------------------------
for(auto& element : container)
...
//----------------------------------------------------

If, however, I mistakenly do it without a reference, will the compiler
be able to optimize the copying of the large elements if it sees that
they are not modified in the loop body?

If the compiler is unable to optimize the copying away, I'm thinking
that the range-based loop is way too easy to use in an inefficient manner
by mistake. This is not a very good thing.

I've thought about that also, but probably if an author
isn't aware of it, someone will catch it in a code review.

I remember a thread a few months ago about studying code
from a project. If such an author studied this code --
http://webEbenezer.net/misc/direct.tar.bz2
they might notice the use of & in this context and
investigate it further.

http://webEbenezer.net
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,968
Messages
2,570,153
Members
46,701
Latest member
XavierQ83

Latest Threads

Top