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;
}

익명 사용자의 이미지

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) 라는 인수로 호출되는거죠..

익명 사용자의 이미지

답변 감사하구요..

이 질문을 여러곳에다가 했는데, 가장 이해가 쉬운 답장을
첨부해서 올립니다.

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

일반 함수 대신에 함수 객체를 사용하는 가장 큰 이유로 세가지를 들 수 있는데, 첫째로, 새로운 함수를 만들
지 않고 표준 라이브러리에서 제공되는 함수 객체를 사용하자는 것이고, 둘째로, 인라인 함수를 호출함으로써
수행속도를 향상하고자 하는 것이고, 셋째로, 함수 객체로 하여금 자신이 가지고 있는 상태정보를 접근하고, 갱
신할 수 있도록 하자는 것이다. 프로그래머 입장에서는 세번째가 가장 매력적인 이유가 아닐까 싶다. 그럼, 각
각의 예를 들어보자

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.