본문 바로가기

[ C/ C++ 프로그래밍 ]/[ STL ]

[ 혼연 정리 ] 함수객체- 2 [알고리즘의 변형]



for_each 처럼 함수 객체를 명시적으로 요구하는 알고리즘도 있고 필요할 때만 함수 객체를 옵션으로 받는 알고리즘도 있다.

find는 순회중의 반복자 값과 세번째 인수로 지정한 값(val)을 == 연산자로 비교하여 정확하게 일치하는 요소를 찾아낸다.
그런대 때로는 ==로 정확한 일치를 검색하는 것이 아니라 사용자가 정의하는 방식으로 검색할 욧소를 골라야 하는 경우도 있다.
이때 함수 객체로 요소를 직접 비교할 수 있는데 이런 함수는 보통 원래 함수의 이름 끝에 _if가 붙는다. find의 함수 객체 버젼은 다음과 같다.

InIt find_if(InIt first, InIt last, UniPred F);

세번째 인수는 F는 () 연산자를 오버로딩하는 함수 객채이며 요소값 하나를 인수로 전달받아 이 값이 원하는 조건이 맞는지 검사하여 bool 형을 리턴한다.
bool을 리턴하는 함수 객체를 특별히 조건자(Predicate)라고 부르는데 요소가 지정 조건을 만족하는 지를 검사하는 역할을 한다.

예제 : find_if

1 #include <iostream>
2 #include <string>
3 #include <vector>
4 #include <algorithm>
5
6 using namespace std;
7
8 struct IsKim
9 {
10     bool operator()(string name) const
11     {
12         return ( strncmp(name.c_str(), "", 2) == 0 );
13     }
14 };
15
16 void main()
17 {
18     string names[] = { "장동건", "김태희", "고소영", "정우성", "이소연",
19         "한예슬", "이동건", "태연", "오방실", "김희선" };
20     vector<string> vs( &names[0], &names[10] );
21
22     vector<string>::iterator it;
23
24     /// 반복자초기화
25     it = vs.begin();
26
27     while(1)
28     {
29         /// 김씨성을가진사람을검색한다.
30         it = find_if( it, vs.end(), IsKim());
31
32         /// 없을경우는Break
33         if ( it == vs.end() )
34         {
35             cout << "검색이완료되었습니다."<<endl;
36             break;
37         }
38
39         /// 김씨성을가진사람을출력
40         cout <<"찾는성을가진사람은"<<  *it<< "입니다." << endl;
41        
42         /// 반복자를증가==> 증가시기키지않으면무한반복
43         it++;
44     }
45 }



다음과 같이 일반 함수를 정의하고 함수 포인터를 전달해도 상과없다

1 bool IsKim(string &name)
2 {
3      return (strncmp(name.c_str(),"",2)==0);
4 }
5
6 it=find_if(vs.begin(),vs.end(),IsKim);

IsKim 다음에 괄호를 적지 말아야 하는데 함수명 자체가 함수 포인터이므로 괄호가 붙을 필요가 없으며 붙어서도 안된다. 함수 포인터를 쓰나 함수 객체를 쓰나 실행 결과는 동일하지만 가급적이면
함수 객체를 쓰는 것이훨씬 유리하다. 순차 검색을 하는 find_if는 각 요소마다 일일이 비교를 하는데 이때마다 실제 함수가 호출된다면 오버헤드가 너무 커지기 때문이다.

함수 객체로 만들때와 함수 포인터를 쓸때 인수의 형태가 조금 달라진다.
함수 포인터 : 레퍼런스로 전달 받는 것이 좋다. string 같이 덩치가 큰 객체를 전달 할때 값으로 받으면 복사가 발행하여 비용이 커진다.
함수 객체 : 크기에 상관없이 값으로 전달받아야 한다. ==> 인라인으로 삽입되기 때문에 인수 전달 과정이 필요 없다.

ps : 자세한 내용은  www.WinAPI.co.kr 참고