32

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.

2
  • 4
    I guess they simplified the examples too much. Once you add additional local variables or parameters, you'd want to capture them by copy. Then the [=, ..] part makes sense (if you don't want to capture them explicitly one-by-one, that is).
    – dyp
    Commented Jan 13, 2017 at 15:14
  • It might be helpful to draw on analogies between non static member functions and other functions, even between C++ and what C++ could have been if, during the history of "C with classes", references came before member functions (this is only pointer because there were no references when it was invented).
    – curiousguy
    Commented Jan 26, 2019 at 3:15

2 Answers 2

35

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

4
  • this is a scalar rvalue since the first "serious" C++ (only in primitive C++ was it assignable), you can't refer to an object this, only to the value of this.
    – curiousguy
    Commented Jan 26, 2019 at 3:08
  • @curiousguy, I'm not sure what your criticism here is. Have I been ambiguous with terminology somewhere? I see that I've written "the (original) object" when talking about *this - is that giving you problems? Commented Jan 28, 2019 at 9:37
  • There is no such thing as the original value of a pointer; a pointer value is a pointer value is a pointer value. "the original this" makes no sense.
    – curiousguy
    Commented Jan 28, 2019 at 17:17
  • Thanks @curiousguy, I think I see what you mean now. I'll try and think of a clearer way to phrase what I meant. (Time passes). Better? Commented Jan 28, 2019 at 18:16
5

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.

Not the answer you're looking for? Browse other questions tagged or ask your own question.