58 votes

Différence entre std :: function <> et un pointeur de fonction standard?

Quelle est la différence entre std :: function <> et un pointeur de fonction standard?

C'est:

 typedef std::function<int(int)> FUNCTION;
typedef int (*fn)(int);
 

Sont-ils effectivement la même chose?

46voto

Kerrek SB Points 194696

Ils ne sont pas du tout la même chose. std::function est complexe, lourd, dynamique, proche de la magie de type qui peut contenir toute sorte de appelable entité, tandis que un pointeur de fonction est vraiment juste un simple pointeur. Si vous pouvez sortir avec elle, vous devriez préférer soit nu pointeurs de fonction ou auto-bind/auto-lambda types. Utilisez uniquement std::function si vous avez vraiment besoin d'un moyen systématique de l'organisation d'une collection hétérogène de appelable entités, telles que les fonctions, les foncteurs, la capture des lambdas et de lier des expressions.


Mise à jour: Un peu d'explications à propos de auto types: Comparer les deux fonctions suivantes:

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

Maintenant, imaginez les invoquer avec un lambda ou un bind expression:

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

La deuxième version du modèle est plus efficace, car dans les deux cas, l'argument F est déduite du réel, de l'inconnaissable type de l'expression. La première version, avec std::function, n'est pas un modèle et peut paraître plus simple et plus délibérée, mais il toujours les forces de la construction de l' std::function objet, et peut-être porte plusieurs type d'effacement virtuel et coûts d'expédition.

45voto

Paul Manta Points 9409

Un pointeur de fonction est l'adresse d'une fonction réelle définie en C++. Un std::function est un wrapper qui peut contenir n'importe quel type d'objet appelable (des objets qui ressemblent à des fonctions).

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

Ici, std::function vous permet de faire abstraction exactement ce genre d'objet appelable c'est vous traitez — vous ne savez pas c'est FooFunctor, vous savez juste qu'il retourne void et a un int paramètre.

Un exemple réel où cette abstraction est utile lorsque vous êtes à l'aide de C++ avec un autre langage de script. Vous pourriez concevoir une interface qui peut traiter à la fois des fonctions définies en C++, ainsi que des fonctions définies dans le langage de script, de manière générique.

Edit: Liaison

Aux côtés std::function,, vous trouverez également std::bind. Ces deux sont des outils très puissants lorsqu'ils sont utilisés ensemble.

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

Dans cet exemple, la fonction de l'objet renvoyé par bind prend le premier paramètre, _1, et le transmet func le a paramètre, et définit b à la constante 5.

11voto

Lalaland Points 4383

Un std :: function a un état. Il peut contenir des paramètres supplémentaires "liés" dans celui-ci.

Ces paramètres peuvent aller d’autres choses que d’autres classes, d’autres fonctions ou même ces pointeurs pour les appels de fonctions membres.

Le pointeur de la fonction de remplacement n'est pas typedef int (*fn)(int);

Il s’agit de typedef int (*fn)(void*,int); , avec le vide * reprenant l’état qui serait caché dans la fonction std ::.

4voto

Non.

L'un est un pointeur de fonction; l'autre est un objet qui sert d'enveloppe autour d'un pointeur de fonction.

Ils représentent à peu près la même chose, mais std::function est beaucoup plus puissant, vous permettant de faire des liaisons et ainsi de suite.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X