I’ve come to C++11 from an Objective-C background, and one thing I’m struggling to come to terms with is the different capturing semantics of C++11 lambdas vs Objective-C “blocks”. (See here for a comparison).
In Objective-C, like C++, the self/this pointer is implicitly captured if you refer to a member variable. But because all objects in Objective-C are effectively “shared pointers”, to use the C++ terminology, you can do this:
doSomethingAsynchronously(^{
someMember_ = 42;
});
… and you’re guaranteed that the object whose member you’re accessing will be alive when the block executes. You don’t have to think about it. The equivalent in C++ seems to be something like:
// I'm assuming here that `this` derives from std::enable_shared_from_this and
// is already owned by some shared_ptr.
auto strongThis = shared_from_this();
doSomethingAsynchronously([strongThis, this] {
someMember_ = 42; // safe, as the lambda holds a reference to this
// via shared_ptr.
});
Here, you need to remember to capture the shared_ptr in addition to the this pointer. Is there some less error-prone way of achieving this?
One of the founding principles of C++ is that you don’t pay for what you don’t use. That means in this case that contexts where taking a
shared_ptrtothisis unnecessary shouldn’t incur any reference counting overhead. This also means that it shouldn’t happen automatically even e.g. as a feature ofenable_shared_from_this, since you might want to pass a short-lived lambda to an algorithm (for_each, etc.) in which case the lambda doesn’t outlive its scope.I’d suggest adapting the lambda-wrapper pattern; in that case it’s used for
movecapture of a large object (How to capture std::unique_ptr "by move" for a lambda in std::for_each), but it can equally be used for shared capture ofthis:Use by inheriting
enable_shared_this_lambdain addition toenable_shared_from_this; you can then explicitly request that any long-lived lambdas take a sharedthis: