list of C++11 lambda's gotcha when capturing by reference

Alec Jacobson

January 11, 2016

weblog/

Here's a little example that produces an (at first glance) unintuitive result.

#include <vector>
#include <iostream>
int main(int argc, char * argv[])
{
  std::vector<std::function<int(void)> > index(10);
  for(int i = 0;i<index.size();i++)
  {
    index[i] = [&i]()
      {
        return i;
      };
  }
  for(int i = 0;i<index.size();i++)
  {
    std::cout<<i<<" "<<index[i]()<<std::endl;
  }
}

I'm constructing a list of lambda functions that simply print their own index in the list. I define each lambda to capture the index i. But actually I'm capturing a reference to a locally scoped variable. I'm pretty sure the behavior here is undefined. The output seems to just pick up the last data in that location i=10 at the end of the loop. So this program prints:

0 10
1 10
2 10
3 10
4 10
5 10
6 10
7 10
8 10
9 10

To get the intended result, I should either maintain another list with the data for each lambda from which I can safely use references if it is in the same scope as the lambda, or I should just pass by value:

...
index[i] = [i]()
...

Wouldn't a compiler warning when capturing locally scoped references be possible/desired?

Comments

January 12, 2016, Colin
A similar (I think) thing is true in Python http://docs.python-guide.org/en/latest/writing/gotchas/#late-binding-closures