Lambda expression covertly captures `this`

Suppose I have the following.

struct A { int x; std::function<int()> f1() { return [=](){ return x; }; } std::function<int()> f2() { return [=](){ return this->x; }; } std::function<int()> f3() { return [this](){ return x; }; } std::function<int()> f4() { return [this](){ return this->x; }; } std::function<int()> f5() { int temp = x; return [=](){ return temp; }; } } 

And now I have the following code.

 auto a = std::make_shared<A>(); a->x = 5; std::function<int()> f = af#(); a.reset(); int x = f(); 

where f# refers to any of f1, f2, f3, f4, f5 .

These functions demonstrate behavior in one of two sets:

  • return 5 when calling ( f5 ) or
  • crashed while trying to dereference nullptr ( f1, f2, f3, f4 ).

I understand that this is because some of them commit " this " in member function A , either implicitly or explicitly.

What is the formal rule defining behavior 1 or 2?

I spent some time on an error caused by something similar to f1 , believing that it would capture x and would never assume that it would capture this , so I decided that it would be useful to get this documentation.

+7
source share
1 answer

A formal rule defining this behavior does not exist. Since this behavior is undefined.

Your lambdas access an object that does not exist. You cannot commit a member variable directly by value; you always grab them this . This means that you grab them by reference. After deleting an object, any attempt to access the remote object leads to undefined behavior.

The exception is f5 , which should return a constant value, guaranteed. It is completely disconnected from the original object.

+8
source

All Articles