Hidden Wonders


Ranged-Based for Loops Copy by Value by Default


Today I was writing some C++ that used a ranged-based for loop. Most of my professional career in C++ has been writing on very old compilers (pre-C++11), so I’d never really gotten to use the range-based for loop extensively since I’d first learned C++ in school.

So today I was working on a personal project and had code something like this:

for (auto p : vec)
    p.num += SOME_VALUE; aaaaaaaaaaaaaaaaaaaaaa

And I was dumbfounded: why was my vector not updating?!

As I quickly learned, you can perform a range-based for loop by reference, so what I really wanted was this:

for (auto &p : vec)
    p.num += SOME_VALUE;

In C++, an & makes all the difference.

Of course, this means you can also do range-based for loops by const reference as well:

for (const auto &p : vec)
    p.num += SOME_VALUE;

I have been enlightened. I guess when I first learned C++ and range-based for loops, I must not have had as good a grasp on the differences between pass-by-value, pass-by-reference, and pass-by-const-reference as I do now. In case you don’t know, we can illuminate that difference by looking at these three examples in order:

  1. In pass-by-value, my variable wasn’t getting updated because we had a copy of the data, not the location as it existed in our std::vector, vec.
  2. In pass-by-reference, our code works as expected because our variable p directly refers to the element in vec.
  3. In pass-by-const-reference, our code would also fail. In practice we could forgo the & and just use const, but that would copy our variables (which could be inefficient if you were looping over a vector of structs, for instance).

Home Top

Site Licensing Site last updated: 2024-06-08