반응형
람다 함수는 보통 '일회성'으로 쓰이며 따로 캡처 '[]' 라는게 존재하지 않는다.
하지만 C++에서는 캡처 '[]'가 존재하는데 이게 왜 존재할까?
C++에서 람다는 객체다.
예를 들어
auto f = [=]() { return x + y; };
이와 같이 코드를 작성했을 때
컴파일러가 이렇게 변환한다.
class __lambda_1 {
int x, y; // [=]로 값 캡처 → 멤버 변수로 복사됨
public:
int operator()() const { return x + y; }
};
즉, 람다는 함수가 아니라 객체다!
그래서 operator()를 가진 함수 객체 (functor) 로 동작한다.
이 말은 곧 —
람다를 변수로 저장하거나, 나중에 다시 호출하거나,
다른 함수로 넘기거나, 비동기 쓰레드에서 돌릴 수도 있다는 뜻이다.
C++ 람다는 단순 “한 번 쓰고 버리는 함수”가 아니라
“상태를 가진 함수 객체”이기 때문에,
복사/참조 개념이 존재한다.
람다를 저장해 두고 나중에 쓰는 대표적인 예시들
1. 나중에 다시 호출하는 예시 (함수 저장용)
#include <iostream>
using namespace std;
int main() {
int x = 10;
// 람다를 변수에 저장
auto printX = [=]() {
cout << "현재 x 값: " << x << endl;
};
cout << "지금은 안 부름\n";
// 나중에 호출
printX();
printX();
}
출력
지금은 안 부름
현재 x 값: 10
현재 x 값: 10
한 번 만든 람다를 여러 번 재사용 가능.
[=] 값 캡처라 원본 x가 바뀌어도 영향 없음.
2. 함수 인자로 전달하는 예시 (콜백 함수처럼)
#include <iostream>
#include <functional>
using namespace std;
void repeatTask(int n, function<void()> task) {
for (int i = 0; i < n; i++)
task();
}
int main() {
int counter = 0;
auto increment = [&]() { counter++; };
repeatTask(5, increment);
cout << "최종 counter: " << counter << endl;
}
출력
최종 counter: 5
increment 람다를 repeatTask() 함수로 전달해서
콜백처럼 재사용 가능.
[&]로 참조 캡처했기 때문에 외부 변수 counter가 실제로 증가함.
3. 쓰레드에서 나중에 실행하기 (비동기 실행)
#include <iostream>
#include <thread>
using namespace std;
int main() {
int value = 10;
// 값 캡처로 안전하게 복사
auto task = [=]() {
this_thread::sleep_for(1s);
cout << "백그라운드에서 실행됨: " << value << endl;
};
thread t(task); // 쓰레드에 람다 전달
t.join();
}
출력
백그라운드에서 실행됨: 10
값 캡처 [=]라서 원본 value가 main에서 사라져도 안전함.
[&]로 캡처했으면 위험 (main의 value가 사라질 수 있음)
4. 동작을 미리 저장해두는 “명령(Command)” 패턴
#include <iostream>
#include <vector>
#include <functional>
using namespace std;
int main() {
int health = 100;
vector<function<void()>> actions;
// 여러 행동을 미리 저장
actions.push_back([&]() { health -= 10; cout << "공격받음! 체력: " << health << endl; });
actions.push_back([&]() { health += 5; cout << "회복! 체력: " << health << endl; });
// 나중에 실행
for (auto &act : actions)
act();
}
출력
공격받음! 체력: 90
회복! 체력: 95
람다를 “행동 단위”로 저장해두고 나중에 순차 실행.
이런 식으로 명령(Command) 패턴 구현 시 자주 사용됨.
5. 이벤트 / 콜백 시스템에서 등록-호출
#include <iostream>
#include <functional>
using namespace std;
function<void()> onClick;
void simulateButtonClick() {
cout << "버튼 클릭!" << endl;
if (onClick) onClick(); // 저장된 람다 호출
}
int main() {
int clickCount = 0;
// 이벤트 콜백 등록
onClick = [&]() {
clickCount++;
cout << "클릭 횟수: " << clickCount << endl;
};
simulateButtonClick();
simulateButtonClick();
}
출력
버튼 클릭!
클릭 횟수: 1
버튼 클릭!
클릭 횟수: 2
실제 GUI나 게임 엔진에서도 이런 방식으로 “이벤트 핸들러”로 람다를 저장해둠.
6. 람다를 반환해서 클로저(closure)처럼 쓰기
#include <iostream>
#include <functional>
using namespace std;
function<void()> makeCounter() {
int count = 0;
return [=]() mutable {
count++;
cout << "현재 카운트: " << count << endl;
};
}
int main() {
auto counter = makeCounter();
counter();
counter();
}
출력
현재 카운트: 1
현재 카운트: 2
[=] + mutable로 캡처한 복사본 내부 상태를 바꾸면서
“상태를 가진 함수 객체(클로저)”처럼 동작.
함수형 언어들의 클로저랑 매우 유사한 패턴임.
반응형
'프로그래밍 언어 > C++' 카테고리의 다른 글
| C++ 객체 정렬 (0) | 2025.11.05 |
|---|---|
| C++ mutable (0) | 2025.11.03 |
| C++ 람다함수 기본편 (0) | 2025.10.31 |
| C++ struct와 class의 차이 (0) | 2025.10.04 |
| C++ string compare 사용법 (0) | 2025.10.01 |
댓글