Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++17 lambda capture *this

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.

like image 874
bolov Avatar asked Jan 13 '17 14:01

bolov


People also ask

What does it mean to lambda capture this?

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.

How do you call a lambda in C++?

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.

What is the use of lambda function in C++?

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.

What is capture list in C++?

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).

What is the use of Lambda in C++?

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:

What is a captured variable in lambda function?

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.

Can lambdas capture a copy of an object created by default?

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:

How do you capture this pointer in lambda function?

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.


2 Answers

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).

like image 181
Toby Speight Avatar answered Oct 20 '22 18:10

Toby Speight


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.

like image 5
Richard Hodges Avatar answered Oct 20 '22 17:10

Richard Hodges