C++20coreadvanced
Lambda Capture of [this] by Value (C++20 Evolution)
C++20 · The Big Four · Compiler flag: -std=c++20
Explanation
Lambdas can capture `this` by value, copying the object.
Real-World Scenario
Capture a game object’s state in a callback without lifetime issues.
Quick Snippet
snippet.cpp
[this] { return x; }; // Captures *this by valueFull Example
lambda_this_capture.cpp
// CodeNebula - C++20 Example: Lambda [*this] Capture
// Compile: g++ -std=c++20 -Wall -Wextra -o example lambda_this_capture.cpp
// Demonstrates capturing *this by value in lambdas. This copies the entire
// object into the lambda closure, making it safe to use even after the
// original object is destroyed.
#include <iostream>
#include <string>
#include <functional>
#include <vector>
// ------------------------------------------------------------------
// 1. Basic [*this] vs [this] capture
// ------------------------------------------------------------------
class Counter {
int count_ = 0;
std::string name_;
public:
Counter(std::string name, int start)
: count_(start), name_(std::move(name)) {}
// Captures pointer to this - dangerous if object is destroyed
auto get_ref_lambda() {
return [this]() {
return name_ + ": " + std::to_string(count_);
};
}
// Captures a COPY of *this - safe even after object destruction
auto get_copy_lambda() {
return [*this]() {
return name_ + ": " + std::to_string(count_);
};
}
// [*this] capture with mutation (must be mutable)
auto get_increment_lambda() {
return [*this]() mutable {
++count_;
return name_ + ": " + std::to_string(count_);
};
}
void increment() { ++count_; }
int count() const { return count_; }
};
// ------------------------------------------------------------------
// 2. [*this] in async-like scenarios
// ------------------------------------------------------------------
class Sensor {
std::string id_;
double reading_;
public:
Sensor(std::string id, double reading)
: id_(std::move(id)), reading_(reading) {}
// Returns a callback that holds a copy of the sensor state
auto snapshot_callback() {
return [*this]() {
std::cout << " Sensor " << id_ << " snapshot: "
<< reading_ << std::endl;
};
}
void update(double val) { reading_ = val; }
};
// ------------------------------------------------------------------
// 3. Class with [*this] in method that returns stored lambdas
// ------------------------------------------------------------------
class Logger {
std::string prefix_;
int level_;
public:
Logger(std::string prefix, int level)
: prefix_(std::move(prefix)), level_(level) {}
auto make_log_fn() const {
return [*this](const std::string& msg) {
if (level_ > 0)
std::cout << " [" << prefix_ << "] " << msg << std::endl;
};
}
};
int main()
{
std::cout << "=== [*this] vs [this] ===" << std::endl;
std::function<std::string()> copy_fn;
{
Counter c("Alpha", 10);
copy_fn = c.get_copy_lambda();
c.increment();
c.increment();
// copy_fn captured *this at count_=10, unaffected by increments
}
// Object c is destroyed here, but copy_fn is safe
std::cout << " Copy lambda (after destroy): " << copy_fn() << std::endl;
std::cout << "\n=== Mutable [*this] ===" << std::endl;
Counter c2("Beta", 0);
auto inc_fn = c2.get_increment_lambda();
std::cout << " " << inc_fn() << std::endl; // copy's count: 1
std::cout << " " << inc_fn() << std::endl; // copy's count: 2
std::cout << " " << inc_fn() << std::endl; // copy's count: 3
std::cout << " Original count: " << c2.count() << std::endl; // still 0
std::cout << "\n=== Snapshot Callbacks ===" << std::endl;
Sensor temp("TEMP-01", 22.5);
auto snap1 = temp.snapshot_callback();
temp.update(25.0);
auto snap2 = temp.snapshot_callback();
temp.update(30.0);
std::cout << " After all updates:" << std::endl;
snap1(); // Shows 22.5
snap2(); // Shows 25.0
std::cout << "\n=== Logger with [*this] ===" << std::endl;
auto log_fn = Logger("APP", 1).make_log_fn();
// Logger temporary is destroyed, but log_fn holds a copy
log_fn("Server started");
log_fn("Accepting connections");
auto silent_fn = Logger("SILENT", 0).make_log_fn();
silent_fn("This won't print");
std::cout << " (silent logger produced no output)" << std::endl;
return 0;
}
/*
Expected output:
=== [*this] vs [this] ===
Copy lambda (after destroy): Alpha: 10
=== Mutable [*this] ===
Beta: 1
Beta: 2
Beta: 3
Original count: 0
=== Snapshot Callbacks ===
After all updates:
Sensor TEMP-01 snapshot: 22.5
Sensor TEMP-01 snapshot: 25
=== Logger with [*this] ===
[APP] Server started
[APP] Accepting connections
(silent logger produced no output)
*/
Run command
g++ -std=c++20 -Wall -Wextra -o example lambda_this_capture.cpp