How to Capture Member Variables in Lambda function in C++?

In this article, we will discuss how to capture member variables from the outer scope.

Wrong way to capture member variable in Lambda — Compile Error

Suppose we have a class OddCounter to keep track of the odd numbers read by the object. Inside its member function, we are creating a lambda function and passing it to the STL algorithm std::for_each. Now, this lambda function needs to capture the member variable mCounter. How do we do it? If we try to capture the member variable directly by value or reference, it will not work, i.e.,

class OddCounter
{
    // tracks the count of odd numbers encountered
    int mCounter = 0;
public:
    int getCount()
    {
        return mCounter;
    }
    void update(std::vector<int> & vec)
    {
        // Capturing member variable by value will not work
        // Will result in Compile Error
        std::for_each(vec.begin(),
                      vec.end(),
                      [mCounter](int element){
                                    if(element % 2)
                                    {
                                        // Accessing member variable from outer scope
                                        mCounter++; 
                                    }
                      });
    }
};

It will result in a compile error. So, how do we capture member variables inside a lambda function?

Correct Way to Capture Member variables inside Lambda Function in C++

When it comes to capturing class member variables inside a lambda expression in C++11, you indeed cannot capture member variables directly by their names because they are not in the local scope—they are part of an object’s state. To capture member variables, you should capture the this pointer, which represents a pointer to the current object instance.

Here is how you can capture the this pointer and access member variables:

std::for_each(vec.begin(),
              vec.end(),
              [this](int element){
                        if(element % 2)
                        {
                            // Accessing member variable through this pointer
                            this->mCounter++; 
                        }
              });

Here is the corrected example of the OddCounter class and its usage:

#include <iostream>
#include <vector>
#include <algorithm>

class OddCounter 
{
    // Tracks the count of odd numbers encountered
    int mCounter = 0;

public:
    int getCount() const 
    {
        return mCounter;
    }

    void update(std::vector<int>& vec) 
    {
        // Capturing this pointer to access member variable mCounter
        std::for_each(vec.begin(),
                    vec.end(),
                    [this](int element){
                                if(element % 2)
                                {
                                    // Accessing member variable through this pointer
                                    this->mCounter++; 
                                }
                    });
    }
};

int main() {
    std::vector<int> vec = {12, 3, 2, 1, 8, 9, 0, 2, 3, 9, 7};
    OddCounter counterObj;

    // Passing the vector to OddCounter object
    counterObj.update(vec);

    int count = counterObj.getCount();
    std::cout << "Counter = " << count << std::endl;

    return 0;
}

Output

Counter = 6

In this corrected version, the update method captures the this pointer and uses it to access mCounter. This is the recommended way to capture and modify member variables inside lambda functions in C++.

To compile this code, you can use the following command on a Linux system:

g++ -std=c++11 example.cpp -o example

Make sure to replace example.cpp with the actual name of your C++ source file. After compiling, you can run the program with ./example.

Summary

To capture member variables inside a lambda function, we cannot capture them directly because they are not in the local scope. Instead, we capture this, which is a pointer to the current object, and through it, we can access all the member variables.

Leave a Comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Scroll to Top