핵심 정리
cpp
// [캡처](매개변수) -> 반환타입 { 본문 }
auto square = [](int x) { return x * x; };
std::cout << square(5); // 25
// 반환 타입은 대부분 생략 가능 (컴파일러가 추론)
auto greet = [](const std::string& name) {
return "Hello, " + name;
};문법
캡처 모드 5가지
캡처 목록 []은 lambda 바깥의 변수를 어떻게 가져올지 결정합니다.
cpp
int x = 10, y = 20;
// 1. 아무것도 캡처하지 않음
auto f1 = []() { return 42; };
// 2. 모든 변수를 값으로 캡처 [=]
auto f2 = [=]() { return x + y; }; // x, y 복사본 사용
// 3. 모든 변수를 참조로 캡처 [&]
auto f3 = [&]() { x = 100; }; // 원본 x 수정
// 4. 특정 변수만 선택 캡처
auto f4 = [x]() { return x; }; // x만 값 복사
auto f5 = [&x]() { x++; }; // x만 참조
auto f6 = [=, &x]() { x = y + 1; }; // y는 값, x는 참조
// 5. init capture (C++14) — 새 변수 생성
auto f7 = [z = x * 2]() { return z; }; // z = 20 (복사본)
auto f8 = [p = std::move(ptr)]() { return *p; }; // 이동 캡처mutable — 값 캡처 변수 수정
값으로 캡처한 변수는 기본적으로 const입니다. 수정이 필요하면 mutable을 붙입니다.
cpp
int count = 0;
// 값 캡처 후 수정 시도 — 오류
// auto inc = [count]() { count++; }; ❌
// mutable로 복사본 수정 허용
auto inc = [count]() mutable { count++; return count; };
inc(); // 내부 복사본만 변경, 바깥 count는 그대로반환 타입 명시
cpp
// 컴파일러가 추론 못하는 경우 명시
auto divide = [](double a, double b) -> double {
if (b == 0) return 0.0;
return a / b;
};제네릭 lambda (C++14)
매개변수 타입에 auto를 쓰면 모든 타입에 동작하는 lambda가 됩니다.
cpp
auto print = [](const auto& val) {
std::cout << val << "\n";
};
print(42);
print("hello");
print(3.14);
// STL과의 조합
std::vector<std::string> words{"banana", "apple", "cherry"};
std::sort(words.begin(), words.end(),
[](const auto& a, const auto& b){ return a < b; });STL 알고리즘과의 조합
cpp
std::vector<int> v{1, 2, 3, 4, 5, 6};
int threshold = 3;
// 필터 + 변환
auto it = std::remove_if(v.begin(), v.end(),
[threshold](int x){ return x < threshold; });
v.erase(it, v.end()); // v = {3,4,5,6}
// 누적 (람다로 연산 커스터마이즈)
int sumOfSquares = std::accumulate(v.begin(), v.end(), 0,
[](int acc, int x){ return acc + x * x; });체크포인트
| 캡처 문법 | 의미 |
|---|---|
[] | 캡처 없음 |
[=] | 바깥 변수 전체를 값으로 복사 |
[&] | 바깥 변수 전체를 참조로 |
[x] | x만 값으로 복사 |
[&x] | x만 참조로 |
[=, &x] | 기본 값 복사, x만 참조 |
[y = expr] | 새 변수 y 초기화 (init capture, C++14) |
mutable | 값 캡처 변수를 본문 안에서 수정 허용 |
주의할 점
[&]로 참조 캡처한 lambda가 바깥 변수의 수명보다 오래 살아있으면 댕글링 참조가 됩니다. 특히 lambda를 콜백으로 저장하거나 비동기 작업에 전달할 때 값 캡처 [=] 또는 init capture [p = std::move(x)]를 우선 고려하세요.
[=]는 this도 암묵적으로 캡처합니다. 멤버 함수 안에서 [=]를 사용하면 this가 복사되는 것이 아니라 포인터가 캡처되므로 객체 수명에 주의해야 합니다.
참고 링크
1 sources