C++17 will add copy capture of this object by value, with a capture specification of [*this]
.
How is this useful? How is it different than capturing this
? Can't this already be achieved in C++14 with [tmp = *this]
?
Bonus for explaining why P0018R3 uses [=, tmp = *this]
instead of [tmp = *this]
in their example. If they had used [tmp = *this]
, all the listed downsides of the C++14 solution would be eliminated.
The lambda is capturing an outside variable. A lambda is a syntax for creating a class. Capturing a variable means that variable is passed to the constructor for that class. A lambda can specify whether it's passed by reference or by value.
A lambda is also just a function object, so you need to have a () to call it, there is no way around it (except of course some function that invokes the lambda like std::invoke ). If you want you can drop the () after the capture list, because your lambda doesn't take any parameters.
C++ Lambda expression allows us to define anonymous function objects (functors) which can either be used inline or passed as an argument. Lambda expression was introduced in C++11 for creating anonymous functors in a more convenient and concise way.
The capture list defines the outside variables that are accessible from within the lambda function body. The only capture defaults are. & (implicitly capture the used automatic variables by reference) and. = (implicitly capture the used automatic variables by copy).
Such a lambda is not only a friend of that class, it has the same access as the class it is declared within has. Lambdas can capture the this pointer which represents the object instance the outer function was called on. This is done by adding this to the capture list:
Because captured variables are members of the lambda object, their values are persisted across multiple calls to the lambda! Much like functions can change the value of arguments passed by reference, we can also capture variables by reference to allow our lambda to affect the value of the argument.
Indeed, it is an error to specify this in the capture list when a default is given. Lambdas can capture a copy of the this object, created at the time the lambda is created. This is done by adding *this to the capture list:
Lambdas can capture the this pointer which represents the object instance the outer function was called on. This is done by adding this to the capture list: When this is captured, the lambda can use member names of its containing class as though it were in its containing class. So an implicit this-> is applied to such members.
How is it useful? It's useful when you need a copy of *this
- for example, when *this
itself is no longer valid by the time the lambda is evaluated.
How is it different from capturing this
? It makes a copy of the object, so that when the lambda is evaluated, its this
pointer refers to the copy, rather than to the original object.
Can it be achieved in C++14 with [tmp = *this]
? It can, but [*this]
is more convenient, as code can be moved without prefixing member access with tmp.
. Otherwise, especially with [=, tmp = *this]
, it's possible to accidentally refer to members of the original object when you meant to refer to the copy (particularly if you're in the habit of cut+paste programming). [=,*this]
is a safer alternative in this case, as the original object is not accessible from inside the lambda's body (at least, not via the this
pointer).
Imagine that *this
is a handle class, which maintains a shared_ptr
to some shared state.
The shared impl is (for example) a protocol handler state machine.
The handle class is passed through a series of asynchronous handlers, so itself must be copyable. Each handler mutates the shared state.
A strong use case for this might be a protocol handler for use with a custom asio
service (for example, an http_protocol_socket
).
[=, tmp = *this]
will promiscuously capture any variables by value, including, rather dangerously, the this
pointer itself, as well as specifically capturing *this
into tmp
.
In this use case it would be dangerous to inadvertently refer to this
in the async handler, because it's likely to be a dangling pointer. This is a bug waiting to happen.
[tmp=*this]
will only capture *this
.
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