In this article, we will discuss how to capture member variables from the outer scope.
Table of Contents
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
Frequently Asked:
- Lambda Functions in C++
- How to Capture Member Variables in Lambda function in C++?
- How to Print a vector in C++?
- C++11 Lambda: Capture Variables by Reference or Value
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.