En utilisant les algorithmes STL, vaut-il mieux passer un pointeur de fonction ou un foncteur?

StackOverflow https://stackoverflow.com/questions/1027610

  •  06-07-2019
  •  | 
  •  

Question

Laquelle de ces 2 méthodes est la meilleure et pourquoi?

Méthode 1:

void fun(int i) {
  //do stuff
}

...
for_each(a.begin(), a.end(), fun);

Méthode 2:

class functor {
public:
  void operator()(int i);
};

...
for_each(a.begin(), a.end(), functor());

Modifier: aurait dû le formuler de la manière suivante: dans quelle situation l'une de ces méthodes est-elle préférable à l'autre?

Merci beaucoup!

Était-ce utile?

La solution

Les foncteurs peuvent (et vont ) être alignés de manière triviale & # 8211; cela n'est pas fait pour les pointeurs de fonction habituels.

Ainsi, les foncteurs ont un réel avantage en termes de performances qui peut être énorme dans des boucles serrées. De plus, les foncteurs sont généralement plus faciles à composer et, en particulier, plus agréables avec la STL: std :: bind x ne fonctionne pas avec les pointeurs de fonction , par exemple.

Je déteste la façon dont ils encombrent le code, mais compte tenu de tous les avantages, je les préférerais à tout moment aux indicateurs de fonction.

Autres conseils

Pour dissiper une idée fausse de ce qu'un compilateur peut intégrer, un compilateur de qualité suffisante peut inclure des pointeurs de fonction. Il peut simplement insérer des objets de fonction en ligne plus facilement car il y a plus d'informations statiques disponibles. Par exemple, un pointeur sur une fonction qui ne prend aucun paramètre et renvoie un booléen est de type bool (*) (), alors qu'un foncteur a un type explicite, à savoir le foncteur, et que l'instanciation de modèle peut appeler statiquement l'opérateur de foncteur, plutôt d'appeler via un pointeur de fonction.

Cependant, dans la pratique, il s’agit essentiellement de donner au compilateur suffisamment d’informations pour optimiser efficacement.

Par exemple, Visual C ++ 2008, à l'aide du code suivant avec optimisations complètes:

#include "stdafx.h"
#include <algorithm>

const char print_me[]= "hello!";

class print_functor
{
public:
    void operator()(char c)
    {
        printf("%c", c);
    }
};

void print_function(char c)
{
    printf("%c", c);
}

int _tmain(int argc, _TCHAR* argv[])
{
    std::for_each(print_me, print_me + sizeof(print_me)/sizeof(print_me[0]), print_functor());
    printf("\n");

    std::for_each(print_me, print_me + sizeof(print_me)/sizeof(print_me[0]), print_function);

    return 0;
}

insère complètement les deux appels std :: for_each . Incidemment, sur le PC, le premier for_each a un lea ecx inutile, [ecx] .

L’un des principaux avantages d’un objet fonction par rapport à un pointeur de fonction est qu’il est plus facile de relier certains arguments lors de la construction de cet objet.

Un exemple de foncteur qui pourrait le faire serait

  class multiplyBy
  {
  private:
      int m_whatToMultiplyBy;
  public:
      multiplyBy(int whatToMultiplyBy) : 
          m_whatToMultiplyBy(whatToMultiplyBy)
      {
      }

      void operator()(int& i)
      {
          i = m_whatToMultiplyBy * i;
      }
  }


  ...

  // double the array
  for_each(a.begin(), a.end(), multiplyBy(2));

Cette "liaison" La boost :: bind et boost :: function si boost est disponible pour vous.

À mon avis, le n ° 1 est préférable, car il est plus simple.

Ce n'est pas parce qu'un objet peut être un objet qu'il doit en être un. Je suis sûr que dans certains cas, le foncteur a du sens, mais dans la plupart des cas, il n’est probablement pas nécessaire.

Un foncteur peut être plus facilement en ligne , ce qui peut être un facteur de prendre en compte lorsque la performance est importante.

# 1 est plus simple de déclarer la fonction
tandis que # 2 le foncteur ressemble plus à un appel de fonction.

(Vous devez parfois désespérer de la syntaxe c ++)

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top