Existe-t-il une pénalité de performance d'exécution lors de l'utilisation d'interfaces (classes de base abstraites) en C ++?
Réponses
Trop de publicités?Réponse Courte: Non.
Réponse Longue: C'est pas la classe de base ou le nombre d'ancêtres d'une classe a dans sa hiérarchie qui l'affectent la vitesse. La seule chose, c'est le coût d'un appel de méthode.
Non virtuel appel de méthode a un coût (mais peut être incorporé)
Une méthode virtuelle appel a un coût légèrement plus élevé que vous avez besoin de regarder pour la méthode à appeler avant de l'appeler (mais c'est une simple apparence de la table jusqu' pas une recherche). Depuis toutes les méthodes d'une interface sont virtuels, par définition, il n'est de ce coût.
À moins que vous écrivez quelque hyper sensible à la vitesse de l'application, cela ne devrait pas être un problème. Le plus de clarté que vous recevrez de l'aide d'une interface est généralement fait pour toute perception diminution de la vitesse.
Les fonctions appelées à l'aide de virtual expédition ne sont pas inline
Il y a une sorte de sanction pour des fonctions virtuelles, qui est facile d'oublier: les appels virtuels ne sont pas intégrées dans un (commune) la situation où le type de l'objet n'est pas de savoir le temps de compilation. Si votre fonction est de petite taille et adapté pour l'in-lining, cette sanction peut être très importante, car vous n'êtes pas seulement l'ajout d'un appel de la surcharge, le compilateur est également limité dans la façon dont il peut optimiser la fonction d'appel (il a à assumer la fonction virtuelle peut avoir changé certains registres ou les emplacements de la mémoire, il ne peut pas propager les valeurs de constante entre l'appelant et l'appelé).
Virtuel coût de l'appel dépend de la plate-forme
Comme pour l'appel surcharge de pénalité par rapport à la normale de la fonction d'appel, la réponse dépend de votre plate-forme cible. Si votre misent sur un PC x86/x64 CPU, la pénalité pour l'appel d'une fonction virtuelle est très petite, moderne x86/x64 PROCESSEUR peut effectuer les branchements indirects sur les appels. Toutefois, si vous ciblez un processeur PowerPC ou certains autres RISC, la plate-forme d'appels virtuel, une sanction peut être très important, car indirects appels ne sont jamais prédit sur certaines plates-formes (Cf. PC/Xbox 360 de la Croix-Plate-forme de bonnes Pratiques de Développement).
Il y a une petite pénalité par appel de fonction virtuelle par rapport à un appel régulier. Il est peu probable que vous observiez une différence à moins que vous ne fassiez des centaines de milliers d'appels par seconde, et le prix vaut souvent la peine d'être payé pour plus de clarté de code de toute façon.
Lorsque vous appelez une fonction virtuelle (dire à travers une interface), le programme a faire un look de la fonction dans un tableau pour voir quelle fonction appeler pour cet objet. Cela donne un petit pénalité par rapport à un appel direct à la fonction.
Aussi, lorsque vous utilisez une fonction virtuelle le compilateur ne peut pas inline l'appel de la fonction. Par conséquent, il pourrait y avoir une pénalité à l'aide d'une fonction virtuelle pour quelques petites fonctions. C'est en général le plus grand spectacle "hit" vous êtes susceptible de voir. - Ce vraiment un problème uniquement si la fonction est petit et a appelé à de nombreuses reprises, dire à partir de l'intérieur d'une boucle.
Une autre alternative applicable dans certains cas est le polymorphisme à la compilation avec des modèles. Il est utile, par exemple, lorsque vous souhaitez faire un choix d'implémentation au début du programme, puis l'utiliser pendant la durée de l'exécution. Un exemple avec le polymorphisme d'exécution
class AbstractAlgo
{
virtual int func();
};
class Algo1 : public AbstractAlgo
{
virtual int func();
};
class Algo2 : public AbstractAlgo
{
virtual int func();
};
void compute(AbstractAlgo* algo)
{
// Use algo many times, paying virtual function cost each time
}
int main()
{
int which;
AbstractAlgo* algo;
// read which from config file
if (which == 1)
algo = new Algo1();
else
algo = new Algo2();
compute(algo);
}
La même chose en utilisant le polymorphisme au moment de la compilation
class Algo1
{
int func();
};
class Algo2
{
int func();
};
template<class ALGO> void compute()
{
ALGO algo;
// Use algo many times. No virtual function cost, and func() may be inlined.
}
int main()
{
int which;
// read which from config file
if (which == 1)
compute<Algo1>();
else
compute<Algo2>();
}