[C++] STL 함수 객체(functor)

STL에서 제공하는 함수 중 for_each라는 녀석이 있습니다. 컨테이너에 담긴 데이터 하나하나에 대해 처리해야할 연산을 지정해 주는 함수인데.. 이 for_each는 세개의 인자를 갖습니다. 첫번째 인자와 두번째 인자는 컨테이너에 저장된 데이터의 범위이고 세번째가 데이터 하나하나에 대해 수행될 연산인데.. 함수나 함수 객체를 인자로 받습니다. 예를 들어 list 컨테이너에 다음과 같은 데이터를 담아 보는 것으로 시작해 보겠습니다.

 list values;

 values.push_back(100);
 values.push_back(200);
 values.push_back(150);
 values.push_back(250);

총 4개의 데이터가 저장된 상태인데.. 이 4개의 데이터 각각에 값 10을 더해 주는 연산을 for_each 함수를 이용해 만들어 보면…

void add10(int& elem)
{
    elem += 10;
}

int main()
{
    ....

    for_each(values.begin(), values.end(), add10);
}

여기서 한발짝 더 나아가.. 재활용을 고려해 10이라는 값의 증가가 아닌 그때 그때 마다 원하는 값만큼 증가시키고자할때.. 함수 객체를 사용하면 매우 유연하게 활용할수있습니다.

class Add {
private:
    int _v;

public:
    Add(int v):_v(v) {}
    void operator() (int &elem) const {
        elem += _v;
    }
};

int main()
{
    ....

    for_each(values.begin(), values.end(), Add(10));
}

즉, 어떤 함수를 만들어 놓고.. 증가하고자 하는 값을 클래스에 대한 필드로 가지도록 하고 () 연산자의 기능을 재정의해줌으로써 클래스 객체를 마치 함수처럼 사용할수있도록 했습니다.

끝으로 함수 객체말고도.. 가장 처음 언급한 함수를 템플릿으로 정의함으로써 원하는 값만큼 증가시키는 기능의 구현도 가능한데.. 아래와 같습니다.

template void add(int &elem)
{
    elem += v;
}

int main()
{
    ....

    for_each(values.begin(), values.end(), add);
}

STL.. 기본만 알아도 무척 편리한데.. 좀더 알면 알수록.. 재미있습니다. 손맛이라고 해야 하나.. C++ 참.. 손맛 나는 언어입니다..

[C++] STL 알고리즘 기본

STL을 사용함에 있어서 STL을 자료구조로써만 바라봤고 자료구조로써만 사용했습니다. 견고하면서 빠르며 융통성이 뛰어난 자료구조로써 말입니다. 이 자료구조에 대한 연산, 즉 알고리즘에 대해서는 간과했고.. 필요한 연산은 STL에서 제공해주고 있다는 것을 알고 있음에도 그냥 제 스스로 코드를 만들 써 왔습니다.

예를 들어서 자료구조로써 링크드 리스트(Linked List)는 STL에서 list 입니다. 자료구조로써 아래와 같이.. 저에겐 매우 익숙한 코드로 데이터를 저정합니다.

#include 
#include 

using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
    list values;
 
    values.push_back(100);
    values.push_back(200);
    values.push_back(150);
    values.push_back(250);

    ... // values의 사용

    return 0;
}

링크드 리스트라는 자료구조가 필요했고.. 매우 효율적이면서도 매우 견고한 링크드 리스트의 구현체로써 STL을 사용해 데이터를 저장합니다. 여기서 저장된 데이터 중 가장 큰 값이 필요할 경우 저는 의례 다음처럼 코딩을 해왔습니다.

list::iterator it;
double minValue = DBL_MAX;
for(it=values.begin(); it!=values.end(); ++it) {
    if(*it < minValue) minValue = *it;
}

printf("%lf\n", minValue);

실제로.. 이렇게 사용해 왔는데요. 아마도 STL을 저보다 더 잘 사용하시는, 대부분 그러하시겠지만.. 정말 이렇게 코딩을 했다고? 하며 실소를 금치 못하실거라 생각됩니다. 네.. 반성중입니다. 다시 초심으로 돌아가서.. 이러한 무지를 버리고 STL에서 제공하는 본연의 기본 알고리즘을 활용하려기에 이 글을 작성해 봅니다.

그렇다면 위의 최소값을 얻기 위한 STL의 방식은 무엇일까요? 아래와 같이 최적화되었으며 빠르며 명확한 방법을 제공합니다.

    list::iterator it;

    it = min_element(values.begin(), values.end());
    printf("%lf\n", *it);

최소값이 아닌 최대값을 구하는 함수는 max_element입니다.

이외에도 어떤 값을 갖는지를 판단하는 함수의 경우는 다음 코드와 같습니다.

    list::iterator it;

    it = find(values.begin(), values.end(), 200);
    if(it != values.end())
    {
        printf("Got it!");
    }

STL에서는 이처럼 매우 효율적인 방식의 알고리즘 함수를 많이 제공하지만 끝으로 정렬 함수를 소개하면서 마무리 하고자 합니다.

sort(values.begin(), values.end());

이제.. 이렇게 블로그를 통해 정리를 해 놓았으니 향후 STL을 이용해 자료구조로써 뿐만 아니라 알고리즘 연산에 대해서도 최대한 STL을 사용해 봐야겠습니다.