STL에서의 함수객체에 대한 질문, 그리고 전처리기에 대한 질문
우선 함수객체에 대한 질문을 올리겠습니다.
지금 보는 책에서는 STL알고리즘을 설명하면서 흔히 쓰이는 3번제 인자인
OP에 대한 이야기를 합니다. 그런데 그중 하나가 OP는(함수객체는)
자신의 내부를 변경하면 안된다고 합니다.
즉
class Nth{ private: int nth; int count; public: Nth(int n): nth(n), coutn(0) {} bool operator() (int){ return ++count == nth; } };
네 이함수는 Nth(int)에서 int값에 상관없이 제일처음 생성자로 너어준
인자를 기억하고 있다가, 한번씩 호출될때 마다 자신의 내부 count를
늘려 N번째 호출될때 true를 반환하는 함수 입니다.
제 질문은 여기서 부터입니다 :D
template <class ForwIter, class Predicate> ForwIter std::remove_if( ForwIter beg, ForwIter end, Predicate [b]op[/b]) { beg = find_if(beg, end, [b]op[/b]); if (beg == end) { return beg; } else { ForwIter next = beg; return remove_copy_if(++next, end, beg, [b]op[/b]); } }
휴~ autoindent없이 코드쓰는건 힘들군요 -_-;;
생각해보니 그냥 IDE환경에서 코드를 쓰고 복사할껄-_-;;
아무튼 위에서 op는 굵은 글씨로 표시를 해뒀습니다.
책에서보면 분명히 위의 OP가 find_if때 사용되고, 만약 제거할 원소가 있다면
remove_copy_if에 인자로 전달된 조건자 OP의 복사본을 사용한다고
나와있습니다.
제 의문은 이것입니다. 보통
int foo(int a)
{
bar1(a); //a를 reference로 받아 적당히 가공
bar2(a);
}
이런 코드에서는 a값이 위의 bar1에서 고친 a값이 그대로 들어가지 않습니까?
즉 함수인자로 받은 변수에 대해서는 그 함수 body안에선 지역변수로써
그대로 기억되는 걸로 알고 있습니다.
그런데 위의 함수객체의 경우 OP를 쓸때마다 새로운 함수객체로 사용되는것
같아서 굉장한 의문입니다 ^^
두번째로 표준에 나와있으니 당연한 되는 이야기지만
bool operator() (int){
//do_something
}
굵게 표시된 것처럼 인자를 아예 이름없이 받는 (선언이 아닌)정의가 가능한지요. ^^
마지막 전처리기 질문입니다 헉헉..
제가 C책을 너무 슬렁슬렁봤는지 몰라도 -_-;; (분명 stroustrup책도 STL
부분뺴고 거의다 봤는데 -_-;;) 제가 모르는 구문이 있더군요
typedef unsigned short int clint; typedef clint CLINT[b][CLINTNMAXDIGIT +1][/b];
도대체 2번재 가 뜻하는 바를 모르겠습니다.
책에는 CLINTNMAXDIGIT가 미리 정의되어있다는 언급은 없구요
그냥 최대자리수를 말한다라고 쓰여있어 정의가 되었는지 안되었는지 모르겠습니다.
아무튼 이건 무슨 의미인가요
개인적으로
typedef A B[C]
이런식의 구문은 처음봐서요 -_-;;
고수들의 가르침을 부탁드립니다.
한가지 더요 ^^remove_if에서내부적으로 remove_c
한가지 더요 ^^
remove_if에서
내부적으로
remove_copy_if를 쓰기전에
find_if를 쓰는건
속도의 문제때문입니까? ^^
저는 왜 find_if를 먼저쓰는지 모르겠어여~~~
코드부분에
[b][/b]
그대로 나오네요 위의 전처리기부분에 헷깔리지 마셔요
C++, 그리고 C++....
죽어도 C++
엑스포 현장에서 글을 쓰게 될 줄은... 저도 참 한심합니다. 부쓰 관리
엑스포 현장에서 글을 쓰게 될 줄은... 저도 참 한심합니다. 부쓰 관리나 하지 kldp 나 기웃거리고... 흠... (중독...) :?
STL 알고리즘에서 사용하는 함수자라는 것은 복사가 되어서 전달됩니다. *이나 &로 넘어가는 것은 없습니다. (여기서는 함수객체만 생각합시다.) 그리고 넘겨주는 형태는 객체이지 타입은 아니죠. 보통 함수객체를 넘길 때의 꼴은 디폴트 생성자를 호출하는 my_func() 이렇게 전달해주는데, 이 디폴트 생성자로 함수객체를 임시로(?) 만들어서 알고리즘에 넘겨줄 때 복사생성자를 이용해서 인자를 넘겨받은 op를 사용합니다. (최적화되면 이 과정은 다 생략할 수 있을 것입니다.)
그런데 remove_if 같은 경우 다시 이것을 find_if 로 넘기고 이때, 다시 복사생성자를 이용한 인자전달이 일어날 것입니다. 그런데 원래의 op와 find_if에 전달된 것은 서로 완전히 다른 객체가 되구요. find_if 호출이 넘어와도 원래의 op에는 아무런 영향을 미치지 못합니다. 다음 원래 넘어온 op를 가지고 remove_copy_if 를 호출한다면 find_if 에서 사용했던 것과 원래의 것은 또 다른 것이 될 것입니다.
이런 류의 알고리즘에 전달되는 함수자가 어떤 상태 (멤버) 를 가지고 있다면 십중팔구 각각의 복사로 인해 원하는 결과를 얻을 수 없을 것입니다. 그래서 static 멤버를 사용하거나 (문제가 당연히 생기겠구요) 그 복사시에 복사되는 것들이 이전 부모에 해당하는 객체들과 연결되어 최종 합계나 결과에 이용되기도 하지만 이것이 STL에서 요구하는 것에 부합되는 것인지는 모르겠습니다. 그리고 일부 알고리즘은 이 제약을 받지 않는 것도 있다고 알고 있습니다.
더 자세한 내용은 STL 책. Effective STL, Tutorial and Reference STL 인가 그런 책을 참고하시고, kldp의 많은 분들이 좋은 답글 남겨주시리라 믿습니다.
2번째 질문은 구분자가 없는 인자를 선언할 수 있는 것인가인데, 됩니다. 함수선언은 원래 타입만 있어도 되구요. 함수를 작성할 때에 그 구분자가 없다면 당연히 해당하는 인자를 사용할 수는 없지만 외부에서 어떤 값을 줄 수는 있습니다. 이렇게 하는 경우의 대표적인 예는 WinMain 같은 함수를 들 수 있습니다. 원래 이 함수의 원형은 미리 선언되어 있는데 이것을 그냥 구분자 있게 한다면 이제 와서 소용없는 몇개의 인자 (함수 내부에서 사용하지 않는) 들 때문에 경고가 발생하는 것을 방지할 수 있습니다.
3번째 질문은 typedef 의 용법이라고 볼 수 있는데, 가능하면 배열은 typedef 하지 말라고 하더군요. 분석해보면 CLINT 라는 타입은 기본요소가 unsigned short int 인 CLINTNMAXDIGIT +1 크기만큼의 배열을 나타냅니다.
CLINT a, b;
a[0] = b[1];
이런식으로 배열로 사용하시면 되겠습니다.
그럼, 이만...
p.s. 전시장에서 글 쓰는게 그리 좋은 상황은 아닙니다. 잘못된 것이 있다면 가차없이 지적해주세요...
답변감사드립니다 ^^
제가 하나 큰 착각을 했었군요
find_if함수 내에서 OP가 그대로 들어가는지 착각을 했습니다.
당연히 find_if에서도 OP가 복사해서 들어가야하는 것인데 -_-;;
다 제가 모자란 탓이죠.
두번째 세번째 답변 감사드립니다.
근데 typedef신기하군요
제 생각이라면
typedef clint[CLINTMAXDIGIT+1] CLINT;
이런식이 훨씩 더 맞는 표현이 아닐까요 ^^
왜냐면
typedef A B; 에서 B는 A의 꼴이되니까요 ;;
C++, 그리고 C++....
죽어도 C++
Re: STL에서의 함수객체에 대한 질문, 그리고 전처리기에 대한 ?
typedef A B[C] 라 하면 이때부터 B 라는 자료형이 만들어진 것입니다.
그럼 이 자료형 B 를 쓰자면 선언해야 되는데 이것은
B b; 의 형태가 되겠죠 이것을 다시 풀면
전처리기는 typedef A B[C] 의 B 자리에 변수이름 b 를 써 넣게 됩니다.
즉 B b; 라는 변수 선언은 A b[C]; 가 되는 것이지요
위에서 bugiii 님이 B a,b; 라고 사용하셨는데
이것은 전처리기가 A a[C],b[C] 라고 해석합니다.
typedef clint[CLINTMAXDIGIT+1] CLINT 이 표현이 더 맞을 것 같지만
말이 안되는게
CLINT A; 라는 코드의 경우
clint[CLINTMAXDIGIT+1] A ; 가 되고 이것은
unsigned short int[CLINTMAXDIGIT+1] A; 이 되서 컴파일러가 알 수 없게 되버립니다.
다소 이상한 듯한 이 typedef 용법은 함수 포인터 선언에서 요긴하게 쓰입니다.
이를테면
typedef int (*pf_GetInt(int* pIint)); 라고 쓰는데
이것을
typedef int (*)(int* pIint)) pf_GetInt; 라고 쓰지는 않죠
Re: 답변감사드립니다 ^^
typedef 문은 macro 정의가 아닙니다. :(
typedef A B; 구문에서 typedef를 빼면 A B;만 남죠? B 라는 변수를 A란 형으로 선언하는 것입니다. typedef이 있다면 B라는 "형"을 A란 형으로 선언하는 것이죠.
배열에서도 마찬가지입니다. int A[100];은 배열 변수 A를 선언하죠? typedef int A[100];은 이 배열에 해당하는 형 A를 선언하는 것입니다.
[quote]이것은 전처리기가 A a[C],b[C] 라고 해석합니다.[/
딴지는 아니구요... typedef 는 전처리기의 영역이 아니라 컴파일러가 해야 하는 일이라고 알고 있어서요... :wink:
[quote="bugiii"][quote]이것은 전처리기가 A a[C],
예 전처리기가 아니고 컴파일러가 하는 일이 맞습니다.(^^)
이해하기는 어렵지만 더 깔끔한 규칙이라서 그렇습니다.
다른 분들이 잘 설명해주셨지만 (...)
변수나 함수를 선언하는 방법과 완벽하게 일치하기 때문에 익숙해지면 더 편리한 깔끔한 규칙이죠.
- 죠커's blog / HanIRC:#CN
댓글 달기