isocpp / CppCoreGuidelines

The C++ Core Guidelines are a set of tried-and-true guidelines, rules, and best practices about coding in C++
http://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines
Other
42.71k stars 5.44k forks source link

Expand F.54: All variable capture should be explicit #1419

Open ZacharyHenkel opened 5 years ago

ZacharyHenkel commented 5 years ago

Alternative title from Meyers15: Avoid default capture modes

As practical experience beyond Scott's extensive analysis from his Item 31, we've seen benefits from requiring developers to explicitly list all of the variables used within the lambda. Specifically it forces examination of the lifetime of each object in cases where the lambda may be executed asynchronously.

hsutter commented 5 years ago

Editors call: But shouldn't a lambda that's executed asynchronously especially default to [=]?

We believe that [&] is the right default capture for a local lambda (e.g., one that is passed to an algorithm call so it lives only for the lifetime of the call), and [=] is the right default capture for a non-local lambda (e.g., one that will be passed to an async worker). Yes, there are times you have to be more specific in addition to that default, but are those defaults really pitfalls?

Could you expand on the benefits you see from listing every individual variable that is captured, perhaps two or three examples?

ZacharyHenkel commented 5 years ago

Borrowing Scott's eloquence, our teams have bought in to his statement "Long-term, it's simply better software engineering to explicitly list the local variables and parameters that a lambda depends on."

The biggest gotchas that we've seen are the inadvertent capture of this or global variables. There's also the long term risk that today's local lambda is asynchronously in the future after refactoring.

shaneasd commented 5 years ago

If the language had the ability to call a function and conveniently pass everything in the current scope as parameters myfunc(EVERYTHINGINSCOPE) I don't think I would use it (come to think of it, I might have just described a macro). Is a captures list fundamentally different to this (in terms of information hiding, minimized coupling)? I would say no in that I conceptually think of the captures list as the parameters to a constructor for my lambda. That said, [&] sure is convenient...