2012-01-29 3 views

답변

34

함수 포인터는 C++에서 정의 된 실제 함수의 주소입니다. std::function은 모든 유형의 호출 가능 객체 (함수처럼 사용될 수있는 객체)를 보유 할 수있는 래퍼입니다.여기

struct FooFunctor 
{ 
    void operator()(int i) { 
     std::cout << i; 
    } 
}; 

// Since `FooFunctor` defines `operator()`, it can be used as a function 
FooFunctor func; 
std::function<void (int)> f(func); 

std::function은 당신이 당신이 그냥 void을 반환 한 int 매개 변수가 있다는 것을 알고는 FooFunctor 알고하지 않습니다 — 다루고있는 무엇을 호출하는 개체 종류를 멀리 정확하게 추상적 인 당신을 수 있습니다.

이 추상화가 유용한 실제 예는 C++을 다른 스크립팅 언어와 함께 사용하는 경우입니다. 스크립트 언어로 정의 된 함수뿐만 아니라 C++에서 정의 된 두 함수를 일반적인 방법으로 처리 할 수있는 인터페이스를 설계 할 수 있습니다.

편집 : std::function의 옆에

바인딩, 당신은 또한 std::bind을 찾을 수 있습니다. 이 두 가지는 함께 사용될 때 매우 강력한 도구입니다. 이 예에서

void func(int a, int b) { // Do something important } // Consider the case when you want one of the parameters of `func` to be fixed // You can used `std::bind` to set a fixed value for a parameter; `bind` will // return a function-like object that you can place inside of `std::function`. std::function<void (int)> f = std::bind(func, _1, 5); 

bind 의해 리턴 된 객체 함수는 제 파라미터 _1 소요하고 a 파라미터로서 func에 전달하고, 정 5b를 설정한다.

+3

여기 _1은 무엇입니까? – makar

+1

@makar 'std :: bind'가 결과 함수의 첫 번째 인수를 나타 내기 위해 사용하는 식별자입니다. 그것은 다음과 같은 것입니다 : void bound (int _1) {func (_1, 5); }'. –

+0

[여기 링크] (http://stackoverflow.com/questions/25848690/should-i-use-stdfunction-or-a-function-pointer-in-c) 함수 포인터와 std :: function 사이에 또 ​​다른 언급 : 람다 캡처는 함수 포인터에서 사용할 수 없습니다. 그래서 람다'[&] (int a, int b) {/ * blah * /}'또는'[=] (int a, int b) {/ * blah * /}'이면 컴파일 오류가 발생합니다. 유효한 형식은'[] (int a, int b) {/ * blah * /}' – r0ng

4

하나는 함수 포인터입니다. 다른 하나는 함수 포인터 주위의 래퍼 역할을하는 객체입니다.

그들은 거의 같은 일을 나타내지 만 std::function는 바인딩과 이것 저것을 할 수 있도록 지금까지 더 강력한 이다.

+0

이 두 변환 사이에 간단한 방법이 있습니까? – phimuemue

+0

@phimuemue : 일반적인 경우에는 의미가 없습니다. –

+0

@phimuemue std :: function을 데이터 포인터로 사용하는 래퍼 함수를 ​​작성한 다음 std :: function을 호출합니다. 함수 포인터가 작동하려면 데이터 포인터가 있어야합니다. – Lalaland

11

std::function에는 상태가 있습니다. 추가 매개 변수를 "바인딩"할 수 있습니다.

이 매개 변수는 다른 클래스, 다른 함수 또는 멤버 함수 호출을위한이 포인터의 범위에서 다양 할 수 있습니다.

는 대체 함수 포인터는 그것은 void*std::function에 숨겨진 될 상태를 reperensting으로, typedef int (*fn)(void*,int);하지 typedef int (*fn)(int);

입니다.

40

이들은 모두 동일하지 않습니다. std::function은 복잡하고 무겁고, 상태가 좋고, 거의 모든 종류의 호출 가능 엔터티를 담을 수있는 거의 매직 (magic) 타입이며, 함수 포인터는 실제로는 단순한 포인터입니다. 도망 갈 수 있다면, 알몸 함수 포인터 또는 auto - bind/auto -lambda 유형 중 하나를 선호해야합니다. 함수, 펑터, 람다 캡처 및 바인드 표현식과 같이 호출 가능한 엔티티의 이기종 컬렉션을 체계적으로 구성해야하는 경우에만 std::function을 사용해야합니다.


업데이트 :auto 유형에 대한 설명의 비트 : 비교하여 다음과 같은 두 가지 기능 :

do_something_X([foo, &bar](int n){ bar += n*foo; },  12); 
do_something_X(std::bind(X::bob, &jim, true, _1, Blue), 13); 
:

void do_something_1(std::function<void(int)> f, int a) { f(a); } 

template <typename F, typename A> void do_something_2(F f, A a) { f(a); } 

이제 람다 또는 bind 표정으로 그들을 호출 상상

템플릿을 사용하는 두 번째 버전이 더 효율적입니다. 두 경우 모두 F은 실제의 알 수없는 유형의 표현식으로 추론됩니다. std::function의 첫 번째 버전은 템플릿이 아니며 더 간단하고 고의적으로 보일 수도 있지만 항상std::function 개체의 생성을 강제하며 여러 유형의 지우기 및 가상 디스패치 비용이 발생할 가능성이 큽니다.

+0

좀 더 혼란 스럽습니까? 즉, 정확히 std :: function을 사용할시기와 함수 포인터를 사용해야하는 경우입니다. 또한, 자동 바인드/자동 람다 (auto-bind/auto-lambda types)가 무엇입니까? – aCuria

+4

@aCuria : 호출 할 수있는 것들의 컨테이너를 만들고 거기에 모든 종류의 혼합형을 넣고 싶다면, std :: function'을 실행하고 모든 것을 변환합니다. 그러나 당신이 항상 진정한 자유 함수를 가지고 있음을 안다면 함수 포인터의 컨테이너를 만들면됩니다. 실제 게시물의 자동 환경 설정에 대해 조금 더 자세히 설명하겠습니다. –

+1

@aCuria : 업데이트되었습니다! –

관련 문제