Now that we're able to use C++11 lambdas in our codebase we're grappling with working out the general principles of how they should be defined and used. I realise that there are certainly subjective elements to this, but I think there are also likely to be some more general rules of thumb that will be useful to the community.
What are the general principles of defining a lambda?
[&]
or value [=]
? What are the performance implications?[&foo]
?Personally, my general principle at the moment is 'Use a lambda whenever you need a simple predicate or comparator', but this may mean I'm missing out on some much more powerful use cases.
These questions are somewhat subjective, but I'll give it a shot:
Capture by reference when you need to modify the values in the enclosing scope (obviously), or when you want to avoid copying heavy variables; capture by value otherwise.
Capture a specific variable by reference if you need to modify it's value in the enclosing scope, but not the values of other variables.
I try to always specify the return type to increase readability (so other people can immediately know the return type, instead of having to parse the lambda to deduce it).
The last one is the most subjective of all, but I personally think that lambdas bigger than ~3-5 lines should be refactored to functions, because long lambdas can reduce readability. However, there can be many exceptions, so this is rather a matter of personal preference and highly depends on the actual code.
Many of those questions have answers based on programmer's taste and his code style.
When should you prefer to capture by reference [&] or value [=]? What are the performance implications?
You will capture by &
when you want change the passed object or you don't want make a copy. Otherwise you can capture by =
.
When should you prefer to capture a variable explicitly, eg [&foo] ?
If you want just capture a specific object you use [&foo]
, it's up to you to make your code more restrict by just passing specific object rather that [&]
to avoid unintended mistakes.
Under what circumstances should you specify a return type?
You will determine a return type (C++11) when you need it. There is no special thing to advise.
How complex can a lambda be before it's better being rewritten as a function?
If you think a function are useful to be reused over many functions you should write it as a normal function. Lambdas usually are useful to solve a local requirement.
Use a lambda whenever you need a simple predicate or comparator
Yes. The predicate or comparator functions where they will not be reused anymore are the popular case to use lambdas.
For your last question: A lambda function is essentially an anonymous function (a function without a name) that’s defined inline. It’s incredibly useful for when you need a small function that does not really seem to justify declaring and defining a normal function. The typical example where a lambda function is handy is for something like a comparison being passed to std::sort. For example:
struct Apple
{
Apple(double weight, int age) :
m_weight(weight),
m_age(age)
{}
double m_weight;
int m_age;
};
int main()
{
vector<Apple> myApples;
myApples.push_back(Apple(0.30, 30));
myApples.push_back(Apple(0.75, 80));
myApples.push_back(Apple(0.55, 90));
sort(myApples.begin(),
myApples.end(),
[](const Apple &a, const Apple &b) -> bool
{
return (a.m_weight < b.m_weight);
});
return 0;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With