2010-02-08 3 views
13

그것은 의 for_each 때문에 컴파일러 수있다 "인라인"그들과 함께 사용할 때와 같은 객체가 성능 이점을 말한다.C++에서 컴파일러가 함수 객체를 "인라인"하는 것은 무엇을 의미합니까? 위키 피 디아 <a href="http://en.wikipedia.org/w/index.php?title=Function_object&printable=yes#Performance" rel="noreferrer">article about function objects</a>에서

나는 문제는이 상황 ... 또는 내가 말할 당황 어떤 맥락에서 의미 정확히 무엇에 약간 안개입니다. 어떤 도움을 주셔서 감사합니다!

답변

11

for_each 템플릿의 마지막 매개 변수는 functor입니다. Functor() 연산자 (가능한 경우 인수가 있음)를 사용하여 "호출 할 수있는"것입니다.

  1. 일반 비 멤버 함수 펑있다 : (고화질)으로 펑 두 가지 특색이있다.
  2. 과부하 된 () 연산자 (따라서 함수 개체)가있는 클래스 형식의 개체도 펑터입니다. 당신이 for_each에 대한 펑로 일반적인 기능을 사용하기를 원한다면

지금, 그것은 for_each 템플릿 [추론] 인수 인스턴스화이 경우 다음

inline void do_something(int &i) { /* do something */ } 

int main() { 
    int array[10]; 
    std::for_each(array, array + 10, &do_something); 
} 

처럼 보일 것이다 <int *, void (*)(int &)> . 이 경우 실제 펑터 값은 함수 포인터로 전달 된 함수 포인터 &do_something입니다. for_each의 관점에서 이것은 런타임 값입니다. 런타임 값이기 때문에 펑터에 대한 호출을 인라인 할 수 없습니다. (함수 포인터를 통해 만들어진 모든 호출을 인라인하는 것은 일반적으로 불가능합니다.

하지만 우리는 대신에 함수 객체를 사용하는 경우 for_each 템플릿 [추론] 인수 <int *, do_something> 인스턴스화되고이 경우

struct do_something { 
    void operator()(int &i) { /* do something */ } 
}; 

int main() { 
    int array[10]; 
    std::for_each(array, array + 10, do_something()); 
} 

을 다음과 같이 코드를 볼 수 있습니다. 내부 for_each에서 펑터에 대한 호출은 do_something::operator()으로 연결됩니다. 호출 대상은 컴파일 타임에 알려지고 고정됩니다. 대상 함수는 컴파일 타임에 알려지기 때문에 호출을 쉽게 인라인 할 수 있습니다.

물론 후자의 경우에는 for_each에 인수로 전달 된 런타임 값이 있습니다. for_each에 전화 할 때 우리가 만드는 do_something 클래스의 [일시적] 임시 인스턴스 일 수 있습니다. 그러나이 런타임 값은 호출 대상에 영향을주지 않으므로 (operator()이 가상 인 경우 제외) 인라인에 영향을 미치지 않습니다.

+0

그러나':: std :: for_each'의 완전한 정의는 컴파일러에서 사용할 수 있습니다. 똑똑한 컴파일러에게는 인라인으로 선언 된 함수의 주소가되는 특정 인수로 호출되는 것을 볼 수 있습니다. 컴파일러는 클래스 메소드 인 것처럼 함수 호출을 인라인 할 수 있어야합니다. – Omnifarious

+2

@Omnifarious : 내 예제에서 당신은'void (int &)'시그너쳐를 갖는 다른 함수로 for_each를 호출 할 수 있으며 컴파일러는 for_each와 동일한 하나의 인스턴스 생성만을 사용합니다 : for_each AnT

+2

예를 들어 (템플릿에 대해 잊어 버려), 내 프로그램에서'void foo (int)'함수를 가지고'foo (1);로 여러 번 호출하면; foo (2); '나는 컴파일러가'foo'에 대해 하나의 함수 본문을 생성하고 다른 인수로 동일한 본문을 실행하도록 기대합니다 : 1, 2, 3. 대신에 컴파일러가'foo '각각 "inlined"상수 1, 2, 3을 사용하면 나는 놀랄 것입니다. 작은'foo'에 대해서는 (그 후 인라인된다면) 괜찮을 것이지만, 더 큰'foo'에 대해서는 바람직하지 않습니다. 당신이 묘사하는 것은 본질적으로 같은 것입니다. – AnT

2

인라인 단지 바로이 함수 본문에 그 기능을 호출 할 때마다 교체 수단. 이 새로운 기능으로 점프 한 후 복귀하는 오버 헤드를 감소시키기 때문에

그것은 작은 기능에 대한 최적화이다.

3

그것은 함수의 정의 (코드) 복사 할 수 있으며, 함수 호출에서 당신을 저장 (간주하는 것은 일부 시스템에서 비싼)을 의미한다. 매크로 대체를 생각해보십시오.

4

인라인 컴파일러 함수 자체의 내용 함수에 대한 호출을 대체 할 수있는 과정이다. 컴파일 할 때 컴파일러가 함수의 내용을 알아야합니다.

함수 포인터가 전달되면 컴파일러에서이를 수행 할 수없는 경우가 종종 있습니다.