Lambda function variables in C++11

c++, c++11, closures, lambda

Solution

You've made it clear that you want to use pointers. So... do that.

But at least use a smart pointer. Proper use of `std::shared_ptr` would prevent a number of problems. Of course, you have to make sure to avoid circular references, but for lambdas, that seems unlikely.

Granted, it's still a terrible idea. But it's only terrible in the sense of being a completely pointless premature optimization done to make yourself feel better about passing things around, rather than having any actual measurable benefit in your code's actual running time. At least with a `shared_ptr`, you're less likely to accidentally delete the memory or run into exception safety issues.

I'm going to ignore the bad C++ practice of heap-allocating something you could just as easily stack allocate, as well as the pain of tracking this memory without the use of a smart pointer. This will assume that you know what you're doing and will instead focus on the "performance" and "memory usage" issues you asked about.

Do not take this as an endorsement of what you're wanting to do.

`std::function` will generally be implemented by doing an internal heap allocation of some object; that's necessary due to the type-erasure. So it will be at least one pointer in size; possibly more. The size of the heap allocation will likely be a vtable pointer + the size of your lambda class. And the size of that is governed by how much stuff you capture and whether it is by value or reference.

Like most C++ standard library objects, `std::function` is copyable. Performing a copy will actually copy it, not do a pretend copy where you now have two objects with the same pointer. So each one will have an independent copy of the internal heap object. That is, copying it will mean doing another heap allocation. This will also copy the lambda itself, which means copying everything that's captured within it.

However, like most C++ standard library objects, `std::function` is movable. This does not do any memory allocation whatsoever.

Therefore, if you want to do this, it's pretty cheap:

std::function<int(int, int)> x1 = [=](int a, int b) -> int{return a + b;};

//usage
void set(std::function<int(int, int)> x);
const std::function<int(int, int)> &get();

set(std::move(x1)); //x1 is now *empty*; you can't use it anymore.

Your `set` function can move it into its own internal storage as needed. Note that `get` now returns a `const&`; this is contingent on the storage for these functions not going anywhere.

How cheap will `move` be? It will probably be the equivalent of copying just the fields of `std::function`, as well as blanking or otherwise neutralizing the original one. Unless you're in performance-critical code, this will not be anything you should ever be concerned about.

Problem

There are two ways to use lambda function variable: ``` std::function<int(int, int)> x1 = [=](int a, int b) -> int{return a + b;}; //usage void set(std::function<int(int, int)> x); std::function<int(int, int)> get(); ``` And: ``` std::function<int(int, int)>* x2 = new std::function<int(int, int)>([=](int a, int b) -> int{return a + b;}); //usage void set(std::function<int(int, int)>* x); std::function<int(int, int)>* get(); ``` I would like to know what are the differences, because I do not know how the lambda function data is stored. I would like to know the best way in terms of peformance, memory usage and the best way to pass a lambda function as argument or return lambda function. I would prefer to use pointers if the size of the lambda function object is bigger than 4 or to avoid errors (if some kind of copy constructor is executed when I do an attribution or if some kind of destructor is executed when I do not want). How should I declare lambda function variables? EDIT I want to avoid copies and moves, I want to continue to use the same function again. How should I change this example? ``` int call1(std::function<int(int, int)> f){ return f(1, 2); } int call2(std::function<int(int, int)> f){ return f(4, 3); } std::function<int(int, int)>& recv(int s){ return [=](int a, int b) -> int{return a*b + s;}; } int main(){ std::function<int(int, int)> f1, f2; f1 = [=](int a, int b) -> int{return a + b;}; f2 = recv(10); call1(f1); call2(f1); call1(f2); call2(f2); } ``` I cannot return reference in the function recv: ``` warning: returning reference to temporary ``` Is this a good solution? ``` int call1(std::function<int(int, int)>* f){ return (*f)(1, 2); } int call2(std::function<int(int, int)>* f){ return (*f)(4, 3); } std::function<int(int, int)>* recv(int s){ return new std::function<int(int, int)>([=](int a, int b) -> int{return a*b + s;}); } int main(){ std::function<int(int, int)> f1 = [=](int a, int b) -> int{return a + b;}; std::function<int(int, int)> *f2 = recv(10); call1(&f1); call2(&f1); call1(f2); call2(f2); delete f2; } ``` EDIT (Conclusion) A lambda function object is like any object that is instance of a class. The rules for allocation, arguments and attribution are the same.

Original source