Lambda Expression: Specifying "this" in the capture clause

I'm reading an article [1] on how to use lambda expressions and have some questions:

1. What is meant by "Only variables that are mentioned in the lambda body are captured when a capture-default is used"? I specifically don't understand what it means for a variable to be "captured" in this sentence.

2. Regarding this code snippet:

1
2
3
4
5
6
7
8
9
struct S { void f(int i); };

void S::f(int i) {
    [&, i]{};      // OK
    [&, &i]{};     // ERROR: i preceded by & when & is the default
    [=, this]{};   // ERROR: this when = is the default
    [=, *this]{ }; // OK: captures this by value. See below.
    [i, i]{};      // ERROR: i repeated
}


What is the intent behind specifying the capture clause [=, *this] and what is an example of its usage?

What is the intent behind specifying the capture clause [=, this] and why is it an error?




[1] https://learn.microsoft.com/en-us/cpp/cpp/lambda-expressions-in-cpp?view=msvc-170
Last edited on
Have you read this?
https://learn.microsoft.com/en-us/cpp/cpp/lambda-expressions-in-cpp?view=msvc-170#capture-clause

A lambda can introduce new variables in its body, and it can also access, or capture, variables from the surrounding scope. A lambda begins with the capture clause. It specifies which variables are captured, and whether the capture is by value or by reference. Variables that have the ampersand (&) prefix are accessed by reference and variables that don't have it are accessed by value.

An empty capture clause, [ ], indicates that the body of the lambda expression accesses no variables in the enclosing scope.

You can use a capture-default mode to indicate how to capture any outside variables referenced in the lambda body: [&] means all variables that you refer to are captured by reference, and [=] means they're captured by value. You can use a default capture mode, and then specify the opposite mode explicitly for specific variables.


To use lambda expressions in the body of a class member function, pass the this pointer to the capture clause to provide access to the member functions and data members of the enclosing class.

The this pointer may be captured by value by specifying *this in the capture clause.
Last edited on
When it comes to lambdas there is a lot more to what they can do than MS "explains." To make the situation worse lambdas have changed since they were first introduced in C++11.

https://en.cppreference.com/w/cpp/language/lambda

Scroll down to the "Lambda capture" section to get a better idea why there are errors and not-errors in your code snippet from MS.

To be honest even the explanation at cppreference is a bit convoluted IMO and needs some "talk to me as if I were a 3 year old" Lucy 'splainin'. The curse of self-teaching....

I would recommend an eBook that delves deep into the nitty-gritty on lambdas, from C++98 to C++20:

https://leanpub.com/cpplambda

Bundle it with the author's C++ Initialization eBook for a really good deal for quite a lot of C++ info.

https://leanpub.com/b/lambdacppmembers

See how things change with each C++ version is never a bad thing.

FYI, I own both eBooks and while I have not done a deep dive into either I have skimmed both and found the material to be more than worth the price.

If you've never run across C++ Stories you should take a peek:

https://www.cppstories.com/p/start-here/

One nice feature of leanpub is buying an eBook that is still being written is cheaper than buying a completed book, and you essentially get "free updates". Even books that are 100% complete can be updated by the author and you can get the newer version without paying more money.

Another author, Nicolai M. Josuttis, with books on leanpub I also own has announced a new book I can't wait for release: C++23 - The Complete Guide:

https://leanpub.com/cpp23

MS wrote:
The this pointer may be captured by value by specifying *this in the capture clause.

That gets rearranged depending on which C++ standard your code is built against, something MS apparently doesn't address:

cppreference wrote:
If the capture-default is =, subsequent simple captures must begin with & or be *this(since C++17) or this(since C++20).
1
2
3
4
5
6
7
8
9
10
struct S2 { void f(int i); };
void S2::f(int i)
{
    [=] {};        // OK: by-copy capture default
    [=, &i] {};    // OK: by-copy capture, except i is captured by reference
    [=, *this] {}; // until C++17: Error: invalid syntax
                   // since C++17: OK: captures the enclosing S2 by copy
    [=, this] {};  // until C++20: Error: this when = is the default
                   // since C++20: OK, same as [=]
}

(From the "Lambda capture" section at https://en.cppreference.com/w/cpp/language/lambda)
Someone wrote:
The this pointer may be captured by value by specifying *this in the capture clause.

I think this is wrong. [*this] captures *this, the object, not the pointer, by value.


George PlusPlus wrote:
1
2
    [=, this] {};  // until C++20: Error: this when = is the default
                   // since C++20: OK, same as [=] 

Note that the implicit capturing of this when using [=] is deprecated in C++20 and might be removed in a future version. You're recommended to capture this or *this explicitly if you need it. The reason for this change is that it can be surprising that the member variables are not copied if you don't realize that what is being captured by value is actually the this pointer.
Last edited on
Thank you all for the clarification and for pointing out what I'd overlooked.

Thanks, George, for the suggestions on supplemental material. I purchased an excellent reference on embedded systems from leanpub [1]. It's a great service and the purchase model makes sense: gives the author a way to update their book to address errata, insert comments. Users can download a specific updated version.

[1] Mastering STM32
https://leanpub.com/mastering-stm32-2nd
Last edited on
Embedded programming is not something I am interested in, if I were I'd have probably purchased that particular book.

When you download your leanpub eBooks in epub and/or pdf formats I suggest an eBook management app to organize and read the eBooks. The one I use is calibre:

https://calibre-ebook.com/
@Peter87, I am cognizant of the how and why of the differences in lambda capture of the this pointer, I am merely pointing out there is a difference between differing C++ standards. Nothing else.

Something that MS Learn (or whatever the hell it is called) kinda half-arsed shows, but doesn't really give IMO as good an answer or explanation as cppreference does of the standards changes.
Registered users can post here. Sign in or register to post.