🔍 std::function에는 함수의 주소를 저장해야 되는가?
정답은:
❌ 항상 함수의 주소만 저장하는 건 아니다.
✅ "호출 가능한 모든 것"을 값처럼 저장한다.
void hello(int x) { std::cout << x << '\n'; }
std::function<void(int)> fn = hello; // 함수 이름만 쓰면 주소로 변환됨
hello는 정적인 주소가 있는 함수니까 OKstd::function<void(int)> fn = [](int x) ⚠️{
std::cout << "lambda: " << x << '\n';
};
std::function은 복사해서 저장하고,std::function<void(const A&)> fn = &A::show;⚠️
fn(a)처럼 객체를 전달해야 실행 가능✅ 예시 2와 예시 3 모두 "함수 객체"를 저장하는 건데,
👉 왜 **예시 2 (람다)**는&없이 저장하고
👉 예시 3 (&A::show)은 & 붙여야 하느냐?
⚡ 핵심 결론부터 말하면:
✔ 람다 자체는 객체이기 때문에 & 필요 없음
✔&A::show는 "함수" 그 자체의 주소이기 때문에 &가 꼭 필요함
std::function<void(int)> fn = [](int x) {
std::cout << "lambda: " << x << '\n';
};
[](int x){ ... } 는 람다 "객체"입니다.struct Lambda { void operator()(int) const {...}; } 를 만든 것과 같아요.std::function<void(const A&)> fn = &A::show;
&A::show는 A 클래스 안의 멤버 함수 주소입니다.A 객체는 없음!show는 객체 없이 호출할 수 없는 멤버 전용 함수니까std::function이 알 수 있어요.람다도 결국 operator()를 가진 객체니까 클래스처럼 생겼는데,
왜 &람다::operator() 없이 그냥 쓰는 거냐?
→ 람다는 이미 객체이고, 그 자체가 호출 가능(callable)한 값이에요.
하지만 A::show는 "코드"일 뿐, 객체 없이 실행할 수 없어요.
| 표현 | 의미 | & 필요 여부 |
|---|---|---|
[](int x){...} | 람다 객체 | ❌ |
Print() | 함수 객체 | ❌ |
hello | 일반 함수 → 주소로 변환됨 | 보통 ❌ |
&A::show | 멤버 함수 주소 | ✅ 반드시 필요 |
| 저장 대상 | 저장 방식 |
|---|---|
| 일반 함수 | 함수 포인터 (주소) 저장 |
| 람다 (캡처 없음) | 함수 포인터처럼 동작 |
| 람다 (캡처 있음) | 객체를 복사해서 저장 → 힙 할당 가능성 |
| 함수 객체 (클래스) | operator()를 가진 객체 저장 |
| 멤버 함수 주소 | 특별한 포인터 형식으로 저장됨 |
✔
std::function에 객체(람다/클래스) 를 넘길 땐&안 붙여도 되고
✔ 멤버 함수나 일반 함수처럼 주소를 넘길 땐&가 필요해요.