top | item 29539857

(no title)

bstamour | 4 years ago

Internally, lambdas are structs with the "function call" operator overload. Context is done via members of the struct: capture by-value, and the struct copies them and stores its own, capture by reference, and the struct member is a reference. There should be zero heap allocation in any case.

discuss

order

jjtheblunt|4 years ago

If I'm reading this right, then "lambda" in C++ isn't "lambda" in Scheme/CommonLisp, where captured variables need be heap allocated rather than stack allocated to construct closures?

bstamour|4 years ago

You're right. Lambdas in C++ are syntactic sugar over something the core language has allowed you to do since before C++98. Since you control which variables you capture into the closure, and how, when writing the lambda, all of the information regarding how to make it (e.g. it's size, data members, etc) is static, and so it does not require the use of the heap at all. A concrete example. The following C++ examples do the same thing, and neither touch the heap:

    // A. Using a struct. The old manual way.
    struct my_lambda {
        my_lambda(int c) : c_(c) {}
        int operator() (int x) const {
            return x == c_;
        }
        int c_;
    };
    
    auto f(vector<int> numbers) {
        my_lambda lam(2);
        // remove all the matching elements
        erase_if(numbers, lam);
        return numbers;
    }

    // B. Using a lambda
    auto g(vector<int> numbers) {
        int c = 2;
        erase_if(numbers, [c](int x) { return x == c; });
        return numbers;
    }

gpderetta|4 years ago

It is complicated. In C++ closures can close over local variables either by value or by reference (the choice can be made for each variable closed over).

When closing over a variable by reference, if the lambda need to survive the local scope heap allocating the closure itself won't help. Instead you need to explicitly heap allocate the closed over variable itself (and close over the, usually smart, pointer).

When closing over by vale, there is no such issue, closed over variables are copied over along the lambda and it can be safely, for example, be returned from a function.

Copying might be expensive if the lambda is closing over an expensive to copy object, but move semantics are always an option.

Lambdas are value types, they are usually copied around. so when closing over ither va

huhtenberg|4 years ago

You capture by value a variable that allocates and you get a heap allocation.

kllrnohj|4 years ago

That's dependent on the captured type's copy (or move) behavior, and is completely different from your claim that how the lambda is used can influence this. Lambdas themselves never heap allocate.