Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

lambda's capture mechanism

Tags:

c++

lambda

I have trouble understanding lambda functions and the mechanism to capture variables, so I did a little testing and arrived at really weird conclusion. that is:

class ClassA
{
public:
  std::function<void()> lambda;
  void DoYourStuff()
  {
    int x;
    x = 1;
    lambda = [=] () { printf("A %d\n", x);};
    lambda();
    x = 2;
    lambda(); 
  }
};

class ClassB
{
public:
  std::function<void()> lambda;
  int x;
  void DoYourStuff()
  {
    x = 1;
    lambda = [=] () { printf("B %d\n", x);};
    lambda();
    x = 2;
    lambda(); 
  }
};

Note: only difference is in placement of x variable; ClassA and ClassB's functions have different output!

A 1
A 1
B 1
B 2

So my questions are:

  1. Is this the desired behaviour?
  2. if i used [&] instead of [=] in ClassA, would those lambdas be identical?
  3. Is there some general rule as to when [=] actually makes copy?
  4. When exactly is the capturing of variables by lambdas supposed to happen?
  5. Can I force lambda to do a re-capture of variables?

Thanks

like image 384
user1316208 Avatar asked Sep 27 '12 13:09

user1316208


People also ask

How does lambda capture work?

By default, variables are captured by const value . This means when the lambda is created, the lambda captures a constant copy of the outer scope variable, which means that the lambda is not allowed to modify them. In the following example, we capture the variable ammo and try to decrement it.

What is lambda capture list?

The capture list defines the outside variables that are accessible from within the lambda function body. The only capture defaults are. & (implicitly capture the used automatic variables by reference) and. = (implicitly capture the used automatic variables by copy).

What is a capture clause?

The Captures Clause of the United States Constitution gives Congress the power to "make Rules concerning Captures on Land and Water." A variety of courts, scholars; politicians, and others have recently cited the Clause to support conflicting arguments about the scope of Congress's power to initiate and prosecute war.

What is the type of a lambda CPP?

The type of a lambda expression is unspecified. But they are generally mere syntactic sugar for functors. A lambda is translated directly into a functor.


1 Answers

The first captures the local variable x by value; so it prints 1 both times, since its copy hasn't changed.

The second captures the local quasi-variable this, not the member variable x. So the body is equivialent to printf("%d\n", this->x);, and will print the new value of 2 after you change x.

If you were to explicitly capture x (i.e. [x](){...}), then you will see the same result as the first.

Is this the desired behaviour?

It's the behaviour specified by the language standard.

if i used [&] instead of [=] in ClassA, would those lambdas be identical?

No, but both would produce the same output. The first would capture the local x by reference, so you will see the change to it.

Is there some general rule as to when [=] actually makes copy?

Yes, it copies the variable when the lambda is created.

When exactly is the capturing of variables by lambdas supposed to happen?

When the lambda is created.

Can I force lambda to do a re-capture of variables?

No. Once it's captured by value, it has its own copy of the variable, with no way to access the original. If you need to see changes to the original, then capture by reference (and take care with object lifetimes).

like image 171
Mike Seymour Avatar answered Sep 30 '22 20:09

Mike Seymour