조건 검색이란?
find의 한계
std::find는 값이 정확히 같은지를 찾을 때 사용합니다.
- 하지만 실제 코드에서는 "조건을 만족하는 첫 원소"를 찾는 경우가 더 많습니다.
- 예: 홀수인가?
- 예: 10으로 나누어 떨어지는가?
- 예: rarity가 Unique인가?
std::find_if
auto it = std::find_if(v.begin(), v.end(), predicate);
predicate(*it)가 true가 되는 첫 요소를 반환합니다.
- 못 찾으면
end()를 반환합니다.
- 성능은 선형 탐색이므로
O(N)입니다.
#include <algorithm> 필요.
Predicate 구현 방식
| 방식 | 설명 |
|---|
| 함수 포인터 | 전역/정적 함수 전달 (상태 전달 어려움) |
| 함수 객체(펑터) | operator()를 가진 타입 (상태 보관 가능) |
| 람다 | 익명 함수 (가독성/지역성 좋아 실무에서 가장 자주 사용) |
Predicate 시그니처 감각
- 핵심은 "요소 1개를 받아
bool 반환"입니다.
const T&로 받으면 복사를 줄일 수 있습니다.
bool IsOdd(int n);
bool IsUnique(const Item& item);
구현 방식별 예시
함수 포인터
bool IsDivisibleBy11(int n) { return n % 11 == 0; }
auto it = std::find_if(v.begin(), v.end(), IsDivisibleBy11);
펑터(상태 보관 가능)
struct HasItemId {
int wantedId;
bool operator()(const Item& item) const {
return item.itemId == wantedId;
}
};
auto it = std::find_if(inventory.begin(), inventory.end(), HasItemId{2});
람다(실무 기본)
int wantedId = 2;
auto it = std::find_if(inventory.begin(), inventory.end(),
[wantedId](const Item& item) {
return item.itemId == wantedId;
});
인벤토리 실전 패턴 (강의 핵심)
유니크 아이템이 있는지 찾기
struct IsUniqueItem {
bool operator()(const Item& item) const {
return item.rarity == Rarity::Unique;
}
};
auto it = std::find_if(inventory.begin(), inventory.end(), IsUniqueItem());
찾은 뒤 처리
if (it != inventory.end()) {
} else {
}
it == end()인지 확인하기 전 *it 역참조하면 안 됩니다.
왜 find_if가 자주 쓰이나?
- 게임/서비스 로직은 값 일치보다 "조건 검색"이 훨씬 많습니다.
- 그래서
find보다 find_if를 더 자주 쓰게 됩니다.
자주 하는 실수 + 체크 질문
자주 하는 실수
| 실수 | 문제 |
|---|
find_if 결과를 바로 *it 사용 | 못 찾은 경우 end() 역참조로 UB |
| Predicate에서 큰 객체를 값 복사 | 불필요한 복사 비용 증가 |
| 조건 로직이 긴데 람다에 모두 몰아넣음 | 가독성 저하 (함수/펑터 분리 고려) |
캡처를 [&]로 남발 | 수명/의도 불명확으로 버그 위험 |
체크 질문 (스스로 답해보기)
find와 find_if의 목적 차이를 말할 수 있는가?
find_if 반환값을 안전하게 처리하는 패턴을 설명할 수 있는가?
- 상태가 필요한 조건 검색에서 펑터와 람다 중 무엇을 선택할지 기준이 있는가?