1. Vấn đề nó giải quyết
Một hành vi ngắn chỉ dùng một lần sẽ bất tiện nếu phải tách thành hàm có tên, nhất là khi nó cần trạng thái xung quanh. Lambda tạo callable không tên và capture list cho biết biến bên ngoài nào trở thành một phần của callable.
2. Kiến thức cần có
Ngày 1-3; biến cục bộ, reference, gọi hàm và object lifetime.
3. Ý tưởng cốt lõi
Lambda giống một function object nhỏ do compiler sinh ra. Capture theo value giữ bản chụp, còn capture theo reference truy cập object gốc nên quy tắc lifetime và thay đổi dữ liệu khác nhau.
4. Cú pháp tối thiểu
int n = 3;
auto by_value = [n] { return n; };
auto by_ref = [&n] { ++n; };5. Cách nó hoạt động
Capture list được xử lý lúc object lambda được tạo, không phải mỗi lần gọi.
Một member dạng value giữ số cũ, còn reference đã capture tiếp tục trỏ tới biến cục bộ ban đầu.
Thay đổi biến gốc ảnh hưởng lambda capture reference nhưng không đổi bản chụp theo value.
6. Lỗi thường gặp
Trả về lambda đã capture biến cục bộ bằng reference sẽ để lại dangling reference khi scope kết thúc.
Trước khi áp dụng mẫu, phải kiểm tra kiểu capture, khả năng thay đổi và việc mọi object được tham chiếu có sống lâu hơn lần gọi lambda hay không.
7. Khi nào nên dùng
Nên dùng khi algorithm hoặc thao tác cục bộ cần callable nhỏ gắn với dữ liệu ở gần.
Tránh dùng khi thân hàm dài, được tái sử dụng rộng hoặc lifetime của dữ liệu capture không rõ ràng.
8. Ví dụ đơn giản
Thuế suất được capture theo value để cố định quy tắc tính, còn bộ đếm số lần gọi được capture theo reference để mọi lần gọi cùng cập nhật một biến.
File .cpp dùng dữ liệu cố định để tự đoán và kiểm tra output.
Mã mẫu hoàn chỉnh
Tệp mã nguồn
cpp14/04_lambda_capture_cpp11_review/main.cpp
#include <iostream>
int main() {
double rate = 0.10;
int calls = 0;
auto add_tax = [rate, &calls](double price) {
++calls; // reference capture changes the original counter
return price * (1.0 + rate); // value capture keeps a snapshot
};
rate = 0.20;
std::cout << "total: " << add_tax(100.0) << "\n";
std::cout << "calls: " << calls << "\n";
}
9. Điều cần nhớ
Capture list là một phần trạng thái của lambda và phải thể hiện rõ bản chụp hay truy cập chung.
Compiler hoặc thư viện luôn theo quy tắc cụ thể; cần kiểm tra kiểu capture, khả năng thay đổi và việc mọi object được tham chiếu có sống lâu hơn lần gọi lambda hay không.
Ưu tiên cách viết nhỏ nhất thể hiện rõ ý định và đo đạc khi hiệu năng thực sự quan trọng.
10. Câu hỏi tự kiểm tra
Dễ — Mục đích chính của Ôn lambda và capture trong C++11 là gì?
Trung bình — Nếu
rateđổi sau khi lambda capture theo value được tạo, lambda dùng mức thuế nào?Khó — Điều gì trở nên không hợp lệ khi lambda dùng
[&local]thoát khỏi scope sở hữulocal?