C와 C++의 함수 포인터와 콜백
이 레슨에서는 C의 함수 포인터와 C++의 람다로 함수를 다른 함수의 매개변수로 넘깁니다.
소개
콜백(callback)은 함수를 다른 함수에 넘겨서, 그 함수가 필요할 때 다시 호출하게 하는 것입니다. 그러면 범용 알고리즘이 구현의 세부 사항을 몰라도 호출하는 쪽이 고른 동작을 실행할 수 있습니다. 예를 들어 같은 apply 함수로 제곱하거나, 두 배로 만들거나, 다른 어떤 변환이든 할 수 있습니다.
핵심 정리
- 포인터는 아직 존재하는 올바른 타입의 객체만 가리키거나 null이어야 합니다.
- 할당한 메모리 영역은 정확히 한 번만 해제해야 합니다.
- 어떤 함수가 메모리를 소유(ownership)하는지, 어떤 데이터는 읽기만 하는지(const) 분명히 하세요.
C와 C++ 코드 예제
C
main.c
#include <stdio.h>
int square(int value) { return value * value; }
int apply(int value, int (*operation)(int)) { return operation(value); }
int main(void) {
printf("%d\n", apply(6, square));
return 0;
}
36
C++
main.cpp
#include <functional>
#include <iostream>
int apply(int value, const std::function<int(int)>& operation) {
return operation(value);
}
int main() {
int factor = 6;
std::cout << apply(factor, [](int value) { return value * value; }) << '\n';
}
36
C와 C++ 비교
C의 매개변수 int (*operation)(int)는 int를 받아 int를 돌려주는 함수를 받는 함수 포인터이므로, apply(6, square)는 36을 돌려줍니다. C++의 람다와 std::function은 더 다양한 호출 가능 객체(callables)를 담을 수 있습니다. 성능이 중요한 코드라면 std::function보다 템플릿이 더 나은 선택인 경우가 많습니다.
C
메모리의 소유와 해제는 전적으로 프로그래머에게 달려 있습니다.
C++
컨테이너와 RAII가 객체의 수명이 끝날 때 자원을 자동으로 해제합니다.
연습 문제
두 버전을 모두 실행한 다음 코드를 바꿔 보면서 각 언어가 주는 안전성의 차이를 살펴보세요.
- 널 포인터와 메모리 할당 실패 상황으로 테스트해 보세요.
- AddressSanitizer와 UndefinedBehaviorSanitizer로 실행해 메모리 오류를 찾아보세요.
- 어떤 포인터가 메모리를 소유하고 어떤 포인터는 읽기만 하는지 분명히 해 보세요.
챌린지로 연습하기
이 레슨에서 배운 내용으로 실제 문제를 풀어 보세요. 모든 챌린지는 브라우저에서 실행되며 즉시 테스트와 AI 리뷰를 받을 수 있습니다.
모든 챌린지