Éviter le coût d'un appel de fonction n'est que la moitié de l'histoire.
faire:
- utiliser
inline
au lieu de#define
- les très petites fonctions sont de bons candidats pour
inline
: un code plus rapide et des exécutables plus petits (plus de chances de rester dans le cache de code)
- la fonction est petite et appelée très souvent
ne pas:
- fonctions volumineuses: conduit à des exécutables plus volumineux, ce qui nuit considérablement aux performances, quelle que soit l'exécution plus rapide résultant de la surcharge d'appel
- fonctions en ligne liées aux E / S
- la fonction est rarement utilisée
- constructeurs et destructeurs: même vide, le compilateur génère du code pour eux
- rupture de la compatibilité binaire lors du développement de bibliothèques:
- en ligne une fonction existante
- modifier une fonction inline ou rendre une fonction inline non-inline: la version précédente de la bibliothèque appelle l'ancienne implémentation
lors du développement d'une bibliothèque, afin de rendre une classe extensible à l'avenir, vous devez:
- ajouter un destructeur virtuel non en ligne même si le corps est vide
- rendre tous les constructeurs non en ligne
- écrire des implémentations non en ligne du constructeur de copie et de l'opérateur d'affectation sauf si la classe ne peut pas être copiée par valeur
Rappelez-vous que le inline
mot-clé est une indication pour le compilateur: le compilateur peut décider de ne pas insérer une fonction et il peut décider d'insérer des fonctions qui n'ont pas été marquées inline
en premier lieu. J'évite généralement la fonction de marquage inline
(à part peut-être lors de l'écriture de très très petites fonctions).
Concernant les performances, l'approche judicieuse est (comme toujours) de profiler l'application, puis éventuellement inline
un ensemble de fonctions représentant un goulot d'étranglement.
Références:
EDIT: Bjarne Stroustrup, le langage de programmation C ++:
Une fonction peut être définie comme étant inline
. Par exemple:
inline int fac(int n)
{
return (n < 2) ? 1 : n * fac(n-1);
}
Le inline
spécificateur est un indice pour le compilateur qu'il devrait tenter de générer du code pour un appel en fac()
ligne plutôt que de définir le code de la fonction une fois, puis d'appeler via le mécanisme d'appel de fonction habituel. Un compilateur intelligent peut générer la constante 720
d'un appel fac(6)
. La possibilité de fonctions en ligne mutuellement récursives, de fonctions en ligne qui se répètent ou non en fonction de l'entrée, etc., rend impossible de garantir que chaque appel d'une inline
fonction est effectivement en ligne. Le degré d'intelligence d'un compilateur ne peut pas être légiféré, donc un compilateur peut générer 720
, un autre 6 * fac(5)
et encore un autre un appel non intégré fac(6)
.
Pour rendre l'inlining possible en l'absence de fonctionnalités de compilation et de liaison inhabituellement intelligentes, la définition - et pas seulement la déclaration - d'une fonction inline doit être dans la portée (§9.2). Un inline
especifier n'affecte pas la sémantique d'une fonction. En particulier, une fonction en ligne a toujours une adresse unique et a donc des static
variables (§7.1.2) d'une fonction en ligne.
EDIT2: ISO-IEC 14882-1998, 7.1.2 Spécificateurs de fonction
Une déclaration de fonction (8.3.5, 9.3, 11.4) avec un inline
spécificateur déclare une fonction en ligne. Le spécificateur en ligne indique à l'implémentation que la substitution en ligne du corps de la fonction au point d'appel doit être préférée au mécanisme d'appel de fonction habituel. Une implémentation n'est pas nécessaire pour effectuer cette substitution en ligne au point d'appel; cependant, même si cette substitution en ligne est omise, les autres règles pour les fonctions en ligne définies au 7.1.2 doivent toujours être respectées.
inline
est au nouveau venu C ++ ce queCFLAGS
sont au nouveau venu Gentoo: non, compiler avec-O3 -funroll-loops -finline-functions
ne fera pas voler votre ancien Pentium;)