Up until now, when looking at [C++ lambda expressions in the `c++11` style](https://en.cppreference.com/w/cpp/language/lambda), I’ve put all of them into two broad categories: capturing and non-capturing.

Non-capturing lambdas, while more restricted in how they can be written, are much more flexible in how they can be used – they can be [implicitly converted to analogous function-pointer types](https://en.cppreference.com/w/cpp/language/lambda#ClosureType::operator_ret.28.2A.29.28params.29.28.29); they don’t encourage gratuitous `std::function<…>` usage, their implementation scope is [less likely to creep out and cause side-effect problems](https://stackoverflow.com/a/21613295/298171), and so on. 

A capturing lambda, however, can be written in a far broader manner. Admittedly, they don’t confer all those benefits I just mentioned. But the capturing lambda makes up for it with the great range of problems it can solve, by breaking out of the confines of the stack’s feed-forward function-call DAG with myriad forms of access to the surrounding scopes.

That’s as far as my understanding goes, however. When I am using capturing lambdas, I tend to explicitly reference-capture specific variables when there are between one and two variables I need:

```cpp
using lambda_t = std::function<std::add_pointer_t<void>(int)>;

lambda_t lambda_explicit = [&one, &another](int descriptor) {
    return ::mmap(nullptr, one, PROT_READ, MAP_PRIVATE, descriptor, another);
};

```

… if there are more than two, I prefer (out of equal parts syntactic OCD and laziness) to eschew explicitly named captures in favor of the reference-to-everything form:

```cpp
lambda_t lambda_everything = [&](int descriptor) {
    return ::mmap(nullptr, one, PROT_READ, MAP_PRIVATE, descriptor, another);
};

```

… which note that changing the form of the lambda’s captures does not alter anything obvious about the lambda’s type – the call signature is the same, for example. This is counterintuitive as it seems that [much of the way capturing works is vaguely specified and somewhat implementation-specific](https://en.cppreference.com/w/cpp/language/lambda#ClosureType::Captures), sort of inversely proportionate to the detailed formal variety afforded by the capture expression (or is it a declaration? or a declaration list?… I am not sure) the full glory of which you’ll see, if you go to that last link and scroll down just a little bit.

I haven’t even touched the overarching majority of the possibilities – I almost always just do either:

1. No capturing at all;
2. One or two explicitly-named variables captured-by-reference; or
3. The indiscriminate capturing-by-reference of everything: `[&]`

What are the circumstances in which I should go out of the way to use one form of capturing over the other? 

Which forms are special-case, and to be generally avoided? Which have tangible penalties – in performance, code size, potential UB, or anything else? Do any capture forms have tangible and/or easy benefits?