2011-01-31 3 views
2

나는 제 I는 A와 B 파라미터 심지어 어떤 괄호없이 펑이 sort_ints에서 언급 된 오퍼레이터() (INT의 A, INT의 B)로 전달 됐는지 궁금에서 WikipediaFunction Objects의 작동을 이해하는데 도움이됩니까?

class compare_class { 
    public: 
    bool operator()(int A, int B) const { 
    return A < B; 
    } 
}; 
... 
// Declaration of C++ sorting function. 
template <class ComparisonFunctor> 
void sort_ints(int* begin_items, int num_items, ComparisonFunctor c); 
... 
int main() { 
    int items[] = {4, 3, 1, 2}; 
    compare_class functor; 
    sort_ints(items, sizeof(items)/sizeof(items[0]), functor); 
} 

에 코드를 발견 .

그런 다음 A와 B가 sort_ints 함수 내부의 함수 객체로 전달되는 것으로 생각했습니다. 그렇다면 sort_ints의 선언에 함수의 주소를 받기 때문에 'ComparisonFunctor c'대신 'ComparisonFunctor * * * c'가 없어야합니까?

sort_ints 함수 안에서 functor에 대한 함수 호출이 다음과 같이 수행됩니까?

functor(*begin_items, *(begin_items+1)); 

답변

6

이 이해하기를, 당신은 객체가 전달되는 것을 기억해야한다 비교기가 반드시 함수 포인터 일 필요는 없기 때문입니다. 예를 들어 compare_class 함수 객체를 사용하여 비교를 수행하는 경우 함수에 전달하는 것은 compare_class 유형의 구체적인 객체입니다. operator()은 무료 함수가 아닌 멤버 함수이므로 compare_class::operator()의 주소를 전달하지 않습니다.

compare_class myComparator; 
myComparator(a, b); 

이 아닌, 그 결과, 상기 파라미터는이 수신기 객체를 필요로하기 때문에, 값보다는 포인터 비교기 취할 필요

compare_class myComparator; 
myComparator.operator() (a, b); 

로 변환 : 그 다음 코드 멤버 함수에 대한 포인터 또는 리시버 개체에 대한 포인터.

+0

sort_ints의 세 번째 매개 변수가 실제로 전체 개체를 값으로 사용한다는 의미입니까? 큰 물체로 작업 할 때 그 점이 좋지 않거나 비효율적이지 않습니까? – Nav

+1

@Nav : 예 - 참조가 더 좋을 것입니다. 그러나 비교 객체는 상태가별로 좋지 않으며 정렬되는 항목의 수에 관계없이 한 번만 전달되기 때문에 큰 문제는 아닙니다. –

+0

@ Nav- 컴파일러는 대개'operator()'를 호출 할 때 수신기 객체를 그림 밖으로 적극적으로 최적화하는 데 정말로 좋습니다. 컴파일러가 어떤 함수가 컴파일 타임에 호출되는지 (수신기의 타입을 알고 있기 때문에) 컴파일러가 해결할 수 있다는 사실과 함께, 원시 함수보다 함수 객체를 사용하는 것이 훨씬 빠릅니다! (실행 파일을 더 크게 만들지 만) – templatetypedef

2

compare_class은 클래스입니다. 따라서 선언 할 수 있고 다른 클래스를 사용하는 방식으로 함수 매개 변수로 전달할 수 있습니다.

둘째, compare_classoperator()을 구현합니다. 이를 통해 다음을 수행 할 수 있습니다.

compare_class obj; 
obj(1, 2); 

이제 위 코드 단락의 두 번째 문은 함수 호출처럼 보입니다! 따라서 어떤 의미에서는 operator()을 구현하는 클래스의 객체는 함수처럼 사용할 수 있습니다.

이것이 바로 기능 개체의 요점입니다. 게다가, 그것은 당신이 당신의 게시물에 준 것과 같은 링크에서 찾을 수있는 함수 포인터보다 다른 장점이 있습니다.

편집

sort_ints() 내부 펑은 다음과 같이 할 것으로 예상된다 : sort_ints이 값의 매개 변수를 사용하는 이유

for (int i = 1; i < num_items; i++) 
    if (c(begin_items[i-1], begin_items[i])) 
    { 
     // begin_items[i-1] is less than begin_items[i], do stuff 
    } 
+0

감사합니다. 그러나 함수 포인터의 일반적인 개념을 이해하려고하지는 않습니다. sort_ints의 내부 코드를 사용할 수 없으며 sort_ints가 함수 포인터를받지 못하는 것 때문에이 특정 예제에서 값이 전달되는 방식을 이해하려고합니다. 나는 그것이 어떻게 작동하는지 당혹 스럽다. – Nav

1

네, 맞습니다. 함수 호출 연산자는 객체의 메서드가 아니라 객체의 이름에 적용됩니다. 게다가 함수의 주소를 전혀 전달하지 않고, 객체를 전달 (복사)하고 있습니다. 펑터 객체에는 데이터 멤버가없고 연산자() 만 있습니다.

template <class ComparisonFunctor> 
void sort_ints(int* begin_items, int num_items, ComparisonFunctor c); 

그리고에서 : 당신이 언급했듯이

3

는, 비교 펑터 자사의 요구 사항에 힌트 sort_ints의 사용에 아무것도 없다 :

compare_class functor; 
sort_ints(items, sizeof(items)/sizeof(items[0]), functor); 

sort_ints 그 자체에 아무것도 없어요 class_compare를 사용하면 다른 기능을 제공하지 않는 것으로 간주하여 사용하는 기능 만 추론 할 수 있습니다.

class compare_class 
{ 
    public: 
    bool operator()(int A, int B) const { return A < B; } 
}; 

컴파일러는 실제로 인스턴스화 된 유형을 사용하여 sort_ints의 구현을 컴파일하려고 시도하기 전까지이를 그대로 두어이 모든 것이 함께 중단되는지 여부를 결정합니다. sort_ints는 귀하가 언급 한 성명과 정확히 일치해야합니다 :

c(*begin_items, *(begin_items+1)); // note: functor argument is "c" 

귀하의 이해는 모든면에서 정확합니다. 그러나 Concepts라는 C++ 0x 기능은 구현을 보지 않고 sort_int의 요구 사항을보다 명확하게하기위한 것입니다. 불행히도 C++ 0x는 최적의 기능을 보장하기에는 시간과 경험이 부족하기 때문에이 기능을 포기해야했습니다. 다행히도 C++의 차기 버전에는 이러한 기능이 통합되어 있기를 기대합니다. 개념에 대한 많은 토론을 '그물'에서 찾아 볼 수 있으며 전반적인 문제를 더 잘 이해할 수 있도록 도와야합니다.

당신이 사용하고자하는 sort_ints 함수와 같은 퍼즐 조각만을 가지고있을 때 ComparisonFunctor 예제가 없으므로 그 Functor를 만드는 방법을 알기 위해 sort_ints 구현을 연구해야하기 때문에 중요한 문제입니다 당신이 아주 행운이고 좋은, 현재의 문서가 없다면). 실수로 코드를 기존 구현에 너무 의존하게 만들 수 있으므로 sort_int 구현이 약간 나중에 변경 될 때 코드가 깨지거나 속도가 느려질 수 있습니다. 테스트 케이스 나 다른 사용자의 코드를 손상시키지 않을 정도로 미묘하더라도 기대. 또한 제공된 ComparisonFunctor의 작은 실수가 sort_int의 어딘가에서 매우 복잡하고 혼란스러운 컴파일러 오류 메시지를 생성 할 가능성이 있습니다. 이는 사용자에게 추상화 된 서비스를 제공하는 좋은 방법이 아닙니다. Concepts가 언젠가 그것을 만들어주기를 희망합시다 ...!