Lambdas represent unnamed functions in C++ programming and can be defined within the code itself. Starting from C++17, developers gained the capability to explicitly capture the *this pointer within lambdas, enabling them to retrieve this pointer from the surrounding class. This enhancement simplifies the utilization of lambdas within class member functions, granting them straightforward access to the class's attributes and functions. This guide delves into the concept of Lambda Capture in C++, covering its syntax, parameters, advantages, and illustrative examples.
Lambda Capture in C++
Lambdas in C++ can be created directly within the code without the need for a distinct function declaration. These anonymous functions have the ability to capture variables from the surrounding scope using capture clauses. Prior to C++17, capturing *this in lambdas was more cumbersome and necessitated alternative solutions.
Lambda Capture of *this in C++17
Capturing the *this pointer in a lambda has become more convenient and intuitive since the introduction of C++17. This feature allows direct utilization of the enclosing class's member variables and functions within the lambda expression.
Benefits of Capturing *this method:
Several benefits of Capturing *this method in C++ are as follows:
- It allows access to member variables and methods, simplifying programming inside member functions.
- It provides a concise and clear syntax for working with class members within lambdas.
- It enables easy parallelization when working with member variables in multithreaded scenarios.
Syntax:
It has the following syntax:
[capture](parameters) mutable -> return_type
{
// lambda body
}
1. Capture Clause ([capture])
The capture clause enables us to designate which variables from the surrounding scope (outside the lambda function) should be accessible within the lambda expression.
The optional [capture] part can be entered in formats as follows:
- : The lambda cannot access any external variables.
- [var]: Captures the value of a particular variable.
- [&var]: Captures a particular variable by reference.
- [=]: Captures all variables by value.
- [&]: Captures all variables by reference.
- [=, &var]: All variables are captured by value, except var, which is captured by reference.
- [&, var]: All variables are captured by reference, except var, which is captured by value.
- Similar to function parameters, this part allows us to specify parameters that can be used within the lambda body.
- It is optional. An empty pair of parentheses can be used without parameters.
- Similar to regular functions, parameters can have types and names.
- If a lambda wants to change variables captured by value, it can utilize the optional mutable keyword.
- Without mutability, variables captured by value are treated as a constant within the lambda body.
- The return type is optional. If omitted, the compiler will deduce the return type.
- If specified, it indicates the return type of the lambda.
- The actual code that the lambda will run is included in the lambda body.
- It has access to the parameters and variables that were captured from the enclosing scope.
- One or more statements may be included in the body.
2. Parameter List ((parameters))
3. Mutable Keyword (mutable)
4. Return Type (-> return_type)
5. Lambda Body ({ // lambda body })
Example:
Let's consider an instance to demonstrate the Lambda Capture of *this function in C++.
#include <iostream>
using namespace std;
class Counter {
public:
// Default constructor initializing count to 0
Counter()
: count(0)
{
}
// Constructor with parameter to initializing count
Counter(int initialCount)
: count(initialCount)
{
}
void Increment()
{
// Define a lambda that captures *this by value
auto incrementLambda = [*this]() mutable {
// Access the count member variable and increment it
count++;
cout << "Incremented count inside lambda: " << count << endl;
};
// Call the lambda to perform the increment
incrementLambda();
}
// Method to increment count by a specific amount
void IncrementBy(int value)
{
// Define a lambda that captures *this by value
auto incrementByLambda = [*this, value]() mutable {
count += value;
cout << "Incremented by " << value << " inside lambda: " << count << endl;
};
// Call the lambda to perform the increment
incrementByLambda();
}
int GetCount() const { return count; }
private:
int count;
};
int main()
{
// Create an instance of the Counter class with an initial count.
Counter counter(5);
// Call the Increment method, which uses a lambda to increment the count.
counter.Increment();
counter.Increment();
// Increment by a specific value using a lambda.
counter.IncrementBy(10);
// Retrieving and printing the updated count.
cout << "The final count is: " << counter.GetCount() << endl;
return 0;
}
Output:
Incremented count inside lambda: 6
Incremented count inside lambda: 6
Incremented by 10 inside lambda: 15
The final count is: 5
Explanation:
This C++ script introduces a class named Counter, designed for controlling a count variable. Within the class are functions that adjust the count within a lambda function. These functions utilize lambda expressions that capture *this by value to increase the count by one or by a designated value. Upon invocation, the Increment and IncrementBy functions display the updated count. The ultimate count is exhibited towards the conclusion of the primary function, which instantiates and interacts with a Counter object through these functions.