When does a variable copy be released in lambda function? - c++

As the example below, I define 2 variables x and y. When I call the lambda function twice, it seems like it will not destroy the copy. From 11.14 — Lambda captures | Learn C++ - Learn C++, it says:
Because captured variables are members of the lambda object, their values are persisted across multiple calls to the lambda!
How does C++ manage the memory for lambda function?
int main() {
int x = 1;
static int y = 1;
auto fun = [=]() mutable{
x++;
y++;
cout<<"Inside:\t\t";
cout<<"x:"<<x<<"\t"<<"y:"<<y<<endl;
};
for (int i = 0; i<2; i++) {
fun();
cout<<"Outside:\t";
cout<<"x:"<<x<<"\t"<<"y:"<<y<<endl<<endl;
}
}
Output:
Inside: x:2 y:2
Outside: x:1 y:2
Inside: x:3 y:3
Outside: x:1 y:3

It stores it inside the object itself. Another way to think of your lambda is below. This is "kind of" equivalent to what the compiler is generating, and yes, I'm changing scopes around a bit and I know that, but this may be clearer to a beginner at C++.
static int y = 1; // Moved this out from main
class my_lambda{
public:
my_lambda(int x) : _x(x) {}
~my_lambda() = default;
void operator()()
{
_x++;
y++;
cout<<"Inside:\t\t";
cout<<"_x:"<<_x<<"\t"<<"y:"<<y<<endl;
}
private:
int _x;
};
int main() {
int x = 1;
my_lambda fun{x}; // "Captures" x
for (int i = 0; i<2; i++) {
fun();
cout<<"Outside:\t";
cout<<"x:"<<x<<"\t"<<"y:"<<y<<endl<<endl;
}
}
As you can hopefully see, the "fake lambda" class I made is doing the same thing your actual lambda is. It "captures" x as part of its constructor and copies it to internal storage, which I called _x. And y is just in scope for it, though I moved to global to be above the class declaration.
I'm overloading the () operator to make a class that's callable, which is a normal thing to do in some circumstances. See operator overloading if you wish for more information.
So this is "kind of, sorta" how lambdas work. They take your body and put it into the operator() of the object that's generated, and anything captured is one of the object's variables, with either the actual object (if by value) or a reference, if captured that way.
And to directly answer your question: when fun goes out of scope, it is freed, both in a lambda, and my case.

Related

Function to Function variables

I'm still relatively new to C++ and I know this might be a rather silly question but is there any way to share a local variable value from one function to another of a different class? Or somehow point a global variable to a function variable using the dereference operator *? Simply put, I need to access local variables of one function and utilize their values in another function of a different class.
For instance:
void CClassX::MyFunction1(){
int x = 8;
}
void CClassY::MyFunction2()
{
x; //utilize x in some way
for(int i; i<x; i++){}
}
Thanks for any comments...
Yes You can do this by sending the variable by reference.And send variable to that particular function in which you want to access.
**void CClassX::MyFunction1()
{
int x = 8;
CClassY::MyFunction2(x)
}
void CClassY::MyFunction2(int &x)
{
x; //utilize x in some way
for(int i; i<x; i++)
{}
}

Binding member function to a local static variable

Precondition:
Here is a function:
typedef std::function<void (int)> Handler;
void g(const Handler& h) {
h(100);
}
, and a class:
class A {
public:
void f0(int n) {
std::cout << m + n << std::endl;
}
void f1() {
::g(std::bind(&A::f0, this, std::placeholders::_1));
}
int m;
};
And this will print two lines, '101' and '102':
int main() {
A a1;
a1.m = 1;
a1.f1();
A a2;
a2.m = 2;
a2.f1();
return 0;
}
Now I realized A::f1() will be called very frequently,
so I modified it like this(new version):
void A::f1() {
static const Handler kHandler =
std::bind(&A::f0, this, std::placeholders::_1);
::g(kHandler);
}
My Questions:
Is it safe to bind this pointer to a local static variable?
Is there no functional difference between two versions?
Can I expect the new version will really gain some performance benefit?
(I suspect my compiler(MSVC) will optimize it by itself,
so I may not need to optimize it by myself).
EDITED ----------
I run the new version and realized that the result is not the same as the original one.
It prints two lines, '101' and '101' again(not '102').
Poor question, sorry for all.
EDITED 2 ----------
Please refer to my new question which I might truly intend:
Binding member function to a member variable
No, this is not safe (nor works as intended). The static variable is shared among all instances to A, and you bind this in this static function object kHandler when calling f1 for the first time. So the bound parameter is always equal to the instance on which you called f1 first, i.e. in your case a1.
It's basically the same with this function:
int f(int a) {
static int b = a;
return b;
}
Call this function multiple times, and you will always get the value of the first call. (Demo)
Alternatives:
You could, if you can live with a space overhead, use a member variable for the bound function, though. I guess implementing this is straight-forward.
A non-thread-safe alternative (I'd not recommend using this!) could be to store the "this" pointer in a static member variable ("that") and make f0 static and use "that" instead of "this":
class A {
static A * that = nullptr;
public:
static void f0(int n) {
assert(that);
std::cout << that->m + n << std::endl;
}
void f1() {
assert(!that);
that = this;
::g(&A::f0);
that = nullptr;
}
int m;
};
Raymond Chen's comment is Correct - by using static you're only ever creating one instance of kHandler, and if the instance of A associated with that first call ever dies, then the bound "this" pointer will be dead.
I recommend removing static:
void A::f1() {
const Handler kHandler =
std::bind(&A::f0, this, std::placeholders::_1);
::g(kHandler);
}
This is safe because kHandler will exist across the lifetime of the g call.

C++ lambda function access write violation

I'm learning how to use C++ lambda functions along with <functional>'s function class. I am trying to solve this Code Golf as practice (challenge is Curry for Dinner)
I have this function:
// This creates a function that runs y a number of
// times equal to x's return value.
function<void()> Curry(function<int()> x, function<void()> y)
{
return [&]() {
for (int i = 0; i < x(); i++)
{
y();
}
};
}
To test this I have this code in my main():
auto x = [](){ return 8; };
auto y = [](){ cout << "test "; };
auto g = Curry(x, y);
This throws Access violation reading location 0xCCCCCCCC. in Functional.h.
Yet when I copy-paste the lambda function from inside Curry() to inside my main like this:
auto x = [](){ return 8; };
auto y = [](){ cout << "test "; };
auto g = [&]() {
for (int i = 0; i < x(); i++)
{
y();
}
};
I get the code running as expected. Why does this happen?
You have a few problems.
Here:
return [&]() {
you capture by reference. Any variables you capture has to have a lifetime that exceeds your own. It means that running the lambda becomes undefined behavior after the variables you capture&use lifetime ends. As you are returning this lambda, and capturing local state, this seems likely to happen. (Note I said variables -- due to a quirk in the standard, [&] captures variables not the data referred to by variables, so even capturing & function arguments by [&] is not safe. This may change in future revisions of the standard... There are neat optimizations that this particular set of rules allow in lambda implementations (reduce [&] lambdas to having 1 pointer worth of state(!)), but it also introduces the only case in C++ where you have a reference to a reference variable in effect...)
Change it to
return [=]() {
and capture by-value.
Or even:
return [x,y]() {
to list your captures explicitly.
When using a lambda which does not outlive the current scope, I use [&]. Otherwise, I capture by value explicitly the stuff I am going to use, as lifetime is important in that case.
Next:
for (int i = 0; i < x(); i++)
you run x once for every loop iteration. Seems silly!
Instead:
auto max = x();
for (auto i = max; i > 0; --i)
which runs max times, and as it happens works if the return value of x was changed to unsigned int or whatever.
Or:
int max = x();
for (int i = 0; i < max; ++i)
which both runs x once, and behaves better if x returns -1.
Alternatively you can use the obscure operator -->:
int count = x();
while( count --> 0 )
if you want to make your code unreadable. ;)

Working with objectives and calling methods?

I've probably become a bit to used to Java and am finding this harder than it should be. Heres what I have.
myObject[0] = new item1(this);
class item1
{
private:
int x;
int y;
public:
item1( passedPointer* pOne )
{
x = 5;
y = 5;
}
int returnX() { return x; }
int returnY() { return y; }
}
Then in another method I thought I could just say:
void check()
{
int y = item1.returnY();
int x = item1.returnX();
}
But I am getting the common error: a nonstatic member reference must be relative to a specific object.
There is only one instance of this class item1, what would be the best way to do this? This is just a simplified fragment of what I'm actually doing, not the actual code.
Item1 is a class. You have to create an instance of it before you can access its non-static members. Try looking here for some basic information.
void check(){
int y = item1.returnY;
int x = item1.returnX;
}
This would also be incorrect in Java, since neither returnX nor returnY are statics, you need an object on which to apply the operation, and you also need the parenthesis of the method call:
void check() {
item1 i;
int y = i.returnY();
int x = i.returnX();
}
Perhaps implementing the Singleton pattern would not do you harm, since you want only one instance of the object. You could declare the object as global or static to a function too, then get the values.
Then again, you could also declare the functions as static, and add another one to initialize the static values of the variables which need to be returned by those methods. There are a lot of solutions to this depending on your situation which can not be fully grasped by the short amount of code you have pasted.
You created an instance of class item1 with the line
myObject[0] = new item1(this);
Unlike JAVA, in C++ there are pointers and new returns a pointer to the object (so myObject[0] is a pointer to the instance) so you need the -> operator. To activate the method you should write:
myObject[0]->returnX();
If you wish to have only one instance than implement the class as a singleton.

references in c++ problem

I heard references in c++ can be intitalized only once but this is giving me 1 is my output and not returning any error!
struct f {
f(int& g) : h(g) {
h = 1;
}
~f() {
h = 2;
}
int& h;
};
int i() {
int j = 3;
f k(j);
return j;
}
The destructor of f is called after the return value j is captured.
You might want something like this, if you wanted j to be 2:
int i( )
{
int j=3;
{
f k(j);
}
return j;
}
See C++ destructor & function call order for a more detailed description of the order of destruction and the return statement.
You are still initializing the reference only once; assignment and initialization are not the same. The initialization sets up h so that it references j (which you never change). Your assignment merely changes the value of j which is the same as h, but does not cause h to refer to a different variable.
I hope this code is only to display the issue, storing a reference to a variable defined outside of the class is very dangerous as your class doesn't have any control over (or knowlege of) when the referenced variable goes out of scope.