STL에서 for_each 알고리즘 활용에 관한 궁금증
STL을 공부중에 아래와 같은 예제를 보았습니다.
#include
#include
#include
using namespace std;
// function object to process the mean value
class MeanValue {
private
long num; // number of elements
long sum; // sum of all element values
public
// constructor
MeanValue () num(0), sum(0) { // <- 궁금증1) 이부분이 초기화를 하는것 같은데
// 함수내에서 num = sum = 0;으로 하는
// 것과 어떤 차이가 있나요?
}
// ``function call''
// - process one more element of the sequence
void operator() (int elem) {
num++; // increment count
sum += elem; // add value
}
// return mean value
double value () {
return static_cast(sum) / static_cast(num);
}
};
int main()
{
vector coll;
// insert elments from 1 to 8
for (int i=1; i<=8; ++i) {
coll.push_back(i);
}
// process and print mean value
MeanValue mv = for_each (coll.begin(), coll.end(), // range
MeanValue()); // operation
/* for_each 알고리즘의 소스를 보면
template
Function for_each(InputIterator first, InputIterator last, Function f) {
for ( ; first != last; ++first)
f(*first);
return f;
}
리턴을 f함수를 실행한 결과를 하는것 같은데,
for_each의 결과를 어떻게 MeanValue라는 클래스에
할당이 가능한지 모르겠네요..
*/
cout << "mean value " << mv.value() << endl;
}
또 이 아래의 소스에서는 클래스가 아니라
함수를 for_each의 인수로 넘겼는데, print라고 된 자리에
클래스 형태의 것이 들어가야 하는 것이 아닌지요?
// function that prints the passed argument
void print (int elem)
{
cout << elem << ' ';
}
int main()
{
vector coll;
// insert elements from 1 to 9
for (int i=1; i<=9; ++i) {
coll.push_back(i);
}
// print all elements
for_each (coll.begin(), coll.end(), // range
print); // operation
cout << endl;
}
Re: STL에서 for_each 알고리즘 활용에 관한 궁금증
MeanValue () num(0), sum(0) { // <- 궁금증1) 이부분이 초 기화를 하는것 같은데
// 함수내에 서 num = sum = 0;으로 하는
// 것과 어 떤 차이가 있나요?
}
--------------------------
변수일경우에는 차이가 없습니다.
초기화 역할을 해주는 역할을 합니다.
그렇지만.. 클래스가 상속을 받았을경우.
부모클래스의 생성자(여러개의 생성자가 있는경우)를 명시적으로 호출할
필요가 있을경우가
필요합니다.
그때 위와 같이 명시하여서..부모클래스 생성자를 선택할 수 있습니다.
명시하지 않으면..기본적으로 default 생성자를 호출하는것으로 알고 있습
니다.
자바 같은 경우에는 super() 가 그런역할을 하죠...
----------------------------------------------------
// ``function call''
// - process one more element of the sequence
void operator() (int elem) {
num++; // increment count
sum += elem; // add value
}
// return mean value
double value () {
return static_cast<double>(sum) / static_cast<double>(num);
}
};
int main()
{
vector<int> coll;
// insert elments from 1 to 8
for (int i=1; i<=8; ++i) {
coll.push_back(i);
}
// process and print mean value
MeanValue mv = for_each (coll.begin(), coll.end(), // range
MeanValue()); // operation
/* for_each 알고리즘의 소스를 보면
template <class InputIterator, class Function>
Function for_each(InputIterator first, InputIterator last, Function f) {
for ( ; first != last; ++first)
f(*first);
return f;
}
리턴을 f함수를 실행한 결과를 하는것 같은데,
for_each의 결과를 어떻게 MeanValue라는 클래스에
할당이 가능한지 모르겠네요..
*/
------------------------------------------------------------------
MeanValue 클래스 정의를 보시면... 분명...operator () 를 재정의 하고
있다는 것을 알수 있습니다.
coll vector 에서 넘어오는 하나 하나의 값을 ..
void operator() (int elem) {
num++; // increment count
sum += elem; // add value
}
을 통해 하나하나 더해가고 있다는 것을 알 수 있겠죠?.
-----------------------------------------------------------------
또 이 아래의 소스에서는 클래스가 아니라
함수를 for_each의 인수로 넘겼는데, print라고 된 자리에
클래스 형태의 것이 들어가야 하는 것이 아닌지요?
-----------------------------------------------------------------
c 에서 함수 포인터라는 개념이 있습니다.
그래서 함수의 주소가지고..해당함수를 실행할 수 있는거죠..
그래서. f(*first) 라는 것이 호출되면..
해당함수에 (*first) 라는 인수로 호출되는거죠..
Re^2: 다른 분께서 답변해준 내용입니다.
답변 감사하구요..
이 질문을 여러곳에다가 했는데, 가장 이해가 쉬운 답장을
첨부해서 올립니다.
http//oopsla.snu.ac.kr/~sjjung/stl/
사이트 운영자님께 질문해서 받은 답장입니다..
==========================
모두 3개의 질문을 하셨습니다.
첫번째는 멤버 초기화와 관련된 질문이었는데, 이것은 method body내에서 초기화하나,
초기화 list에서 하나 똑같습니다. 단지 syntactic sugar라고 해서, 코드를 보기 좋게
만들어주기 위해 C++에서 추가로 제공하는 syntax라고 보시면 되겠습니다.
두번째와 세번째 질문은 모두 for_each의 세번째 인자와 관련된 것입니다.
아시다시피, STL에서 제공되는 많은 알고리듬이 함수 객체(function object)를 인자로 받아
알고리듬의 작동방식을 세밀하게 조절할 수 있도록 하고 있습니다.
for_each도 그중의 하나지요. 따라서, STL 알고리듬을 잘 사용하려면,
함수 객체에 관한 이해가 선행되어야 합니다. 처음 접하시는 분들에게는 조금
까다로운 부분이기도 합니다만... 제 사이트의 3장에도 설명이 되어있습니다.
함수객체는 크게 두가지로 분류할 수 있습니다.
1. 함수 호출 연산자, operator()을 overloading하여 정의한 클래스를 통해 만든
객체를 또한 함수 객체라고 부릅니다.
2. 그리고, 우리가 일반적으로 사용하고 있는 평범한 함수(function)도
넓은 의미에서는 함수 객체라 할 수 있습니다.
따라서, 님의 코드에서 첫번째 for_each에서는 operator()을 정의한 클래스의 객체를
세번째 인자로 넘긴 것이고, 두번째 for_each에서는 그냥 일반 함수를 세번째 인자로
넘긴 것이 되겠습니다.
첫번째 for_each에서는 MeanValue()라는 함수객체를 인자로 넘겨주는데, for_each 내부에서는
컨테이너 내의 원소들을 순회할 때마다 인자로 넘겨받은 함수 객체의 operator() 연산자를 호출하게 됩니다.
(주석내에 적은신 for_each 소스를 보면 f를 인자로 받아 f(*first)를 호출하잖아요? 이부분에서
operator()를 호출하게 되는 겁니다.)
즉, 아래 메쏘드를 호출하게 되는 것이지요. 그러면, MeaValue 객체 내의 num 멤버와 sum 멤버의 값이
계속 증가하겠지요.
void operator() (int elem) {
num++; // increment count
sum += elem; // add value
}
알고리듬 수행이 다 끝나면, for_each는 다시 함수 객체를 리턴하게 되는데,
이 함수 객체의 내부에는 num값과 sum값이 저장되어 있으므로, value() 메쏘드를 리턴값으로 받은
함수 객체에 대해 호출하면 sum/num 즉, 평균값을 얻을 수 있게 되는 겁니다.
두번째 for_each에서는 그냥 일반 함수를 세번째 인자로 넘겨주었는데, 이때에도 f(*first) 이 수행될때,
print(*first)가 수행되는 것이지요. 따라서, 컨테이너의 각 원소를 순회하면서 표준 출력(cout)으로
결과를 계속 출력하게 됩니다.
함수 객체와 일반 함수를 모두 for_each의 세번째 인자로 사용할 수 있지만,
평균값을 구하기 위해 for_each를 사용하는 것과 같이, for_each를 수행하면서 어떤 값을 저장하고
싶을 때는 함수 객체를 사용할 수 밖에 없다는 것을 이해하셨을겁니다. 그냥 함수를 사용하게 되면
상태 정보를 저장할 수가 없게되죠.
필요에 따라, 그냥 함수 객체를 사용하느냐, 아니면 일반 함수를 사용하느냐를 결정하시면 되겠습니다.
==========================================
그 사이트의 3장의 내용..
http//oopsla.snu.ac.kr/~sjjung/stl/fun_0476.htm
일반 함수 대신에 함수 객체를 사용하는 가장 큰 이유로 세가지를 들 수 있는데, 첫째로, 새로운 함수를 만들
지 않고 표준 라이브러리에서 제공되는 함수 객체를 사용하자는 것이고, 둘째로, 인라인 함수를 호출함으로써
수행속도를 향상하고자 하는 것이고, 셋째로, 함수 객체로 하여금 자신이 가지고 있는 상태정보를 접근하고, 갱
신할 수 있도록 하자는 것이다. 프로그래머 입장에서는 세번째가 가장 매력적인 이유가 아닐까 싶다. 그럼, 각
각의 예를 들어보자
댓글 달기