Quand un compilateur inline un appel a une fonction inline, le code de la fonction est insere dans le code de la
fonction appelante (conceptuellement c'est similaire a ce qui se passe avec une macro
Il y a plusieurs facons differentes de marquer une fonction inline, l'une d'elle utilise le keyword inline, d'autres pas. Quelquesoit la facon dont vous marquez une fonction inline, c'est un conseil que le compilateur peut decider d'ignorer: il a le droit de dupliquer toutes, aucunes ou quelques appels a cette fonction inline. (Ne soyer pas decourager si cela vous semble vague. Cette flexibilite est en fait un gros avantage: cela laisse le compilateur traite les grosses fonctions differemment des petites, de plus le compilateur peut generer du code plus facile a debugger si vous choisissez les bonnes options de compilation).
[ Haut | Bas | Rechercher ]
Voyons l'appel a la fonction g():
void f() { int x = /*...*/; int y = /*...*/; int z = /*...*/; ...code that uses x, y and z... g(x, y, z); ...more code that uses x, y and z... }
Imaginons une implementation typique du C++ avec des registres et une pile, les registres et parametres sont ecrit sur la pile avant l'appel a g(), puis les parametres sont lus de la pile dans g() et lus encore pour restaurer les registres quand g() retourne vers f(). Mais c'est beaucoup de lecture/ecriture pour rien, surtout dans les cas ou le compilateur peut utiliser les registres pour les variables x, y et z.
void g(int x, int y, int z) { ...code that uses x, y and z... }
Si le compilateur peut inliner l'apple a g(), toutes operations en memoire peuvent etre elimines. Les registres n'ont plus besoin d'etre ecrit ni lu puisqu'il n'y a plus d'appel de fonction et les parametres n'ont plus besoin d'etre ecrit ni lu puisque le compilateur sait qu'ils sont deja dans les registres.
Bien le resultat va dependre selon les cas et il y a des millions de variables a prendre en compte qui sont en dehors de cette FAQ mais que cet exemple vous serve pour illustrer le genre de chose qui peuvent etre realiser.
[ Haut | Bas | Rechercher ]
Oui et non. Des fois. Peut etre.
Il n'y a pas de reponses simples. Les fonctions inline peuvent rendre le code plus rapide, elles peuvent aussi le rendre plus lent. Elles peuvent rendre l'executable plus gros, elles peuvent aussi le rendre plus petit. Elles peuvent 'trasher' le system, elles peuvent aussi empecher de 'trasher'. Et elles peuvent, souvent, n'avoir aucun impact sur la vitesse.
Les fonctions inline peuvent rendre le systeme plus rapide: Comme montre ci-dessus, la fusion de procedure peut enlever un paquet d'operations inutiles, ce qui peut rendre les choses plus rapide.
Les fonctions inline peuvent rendre le systeme plus lent: Trop de fonctions inlines peut augmenter la taille du code, ce qui peut avoir comme consequence que le systeme 'trashe' sur un syteme a memoire virtuelle. C'est a dire que si l'executable devient trop gros, le systeme peux passer la majorite de son temps a lire des bouts de code du disque vers la memoire.
Les fonctions inline peuvent rendre le systeme plus gros: C'est le probleme de 'code bloat', telle que decrite plus haut. Par exemple, si un system a 100 fonctions inline avec une taille de 100 bytes de code et que ces fonctions sont appeles a 100 endroits differents, cela va conduire a une augmentation de 1MB de l'executable. Est ce que ce 1MB va causer des problemes? Qui sait, mais il est possible que ce dernier 1MB va faire que le systeme va 'trasher' et ralentir l'execution.
Les fonctions inline peuvent rendre le systeme plus petit: Le compilateur genere souvent plus de code pour faire les push/pop des registres/parametres que pour remplacer le corps des fonctions inlines. Cela arrive pour des fonctions qui sont tres petites ou tres longues quand le compilateur peut enlever du code qui est devenu redondant apres la fusion des procedures.
Les fonctions inline peuvent faire trasher: Puisque les fonctions inline peuvent augmenter la taille de l'executable, cela faire trasher le systeme.
inline functions can prevent thrashing: When
Les fonctions inline n'ont aucun impact sur les performances: La plupart des systemes ne sont pas limites par la vitesse du processeur. Ils sont soit limites par les I/O, les acces database ou le reseau. A moins que votre "CPU chronmetre" is bloque a 100%, les fonctions inline ne vont probablement pas rendre votre systeme plus rapide. (Meme avec un systeme qui est limite par le CPU, les fonctions inline n'aideront que si elles sont utilisees sur le point critique du code et ce point critique ne concerne qu'un petit pourcentage du code.)
Il n'y a pas de reponses simples: Il faut jouer avec le systeme pour voir ce qui donne le meilleur resultat. Ne vous baser pas sur des regles trop simples telles que "ne jamais utiliser des fonctions inline" ou "toujours utiliser des fonctions inline" ou "ne mettre inline que des fonctions qui font moins que N lignes". Ce genre de regle generale donne toujours des resultats sub-optimal.
[ Haut | Bas | Rechercher ]
Malheureusement ceci impose de renoncer à la sûreté de type, et impose également un appel de fonction pour accéder même aux zones insignifiantes du struct (si vous permettiez l'accès direct au champs du struct, chacun pourrait accèder directement à tout le struct puisqu'il connaîtrait nécessairement les données pointées par void *, et il deviendrait difficile de changer la structure de données sous-jacentes).
Le temps passé dans l'en-tête d'appel de fonction est court, mais il s'ajoute à chaque appel. Les classes C++ permettent à ces appels de fonction d'être insérés inline. Ceci vous laisse la sûreté de l'encapsulation avec en plus la vitesse des accès directs. En outre, les types des paramêtres de ces fonctions inline sont contrôlées par le compilateur, ce qui est une amélioration par rapport aux macros #define du C.
[ Haut | Bas | Rechercher ]
Contrairement aux macros #define, les fonctions inline évitent les erreurs infâmes liées aux macros puisque les fonctions inline évaluent toujours chaque argument une fois exactement. En d'autres termes, appeler une fonction inline est sémantiquement équivalent à appeler une fonction régulière, mais plus rapidement:
// Une macro qui retourne la valeur abolue de i #define unsafe(i) \ ( (i) >= 0 ? (i) : -(i) ) // Une fonction inline qui retourne la valeur absolue de i inline int safe(int i) { return i >= 0 ? i : -i; } int f(); void codeUtilisateur(int x) { int rep; rep = unsafe(x++); // Erreur! x est incremente deux fois rep = unsafe(f()); // Danger! f() is appele deux fois rep = safe(x++); // Correct! x est incremente une fois rep = safe(f()); // Correct! f() est appele une fois }
Egalement au crédit des fonctions inline par rapport aux macros #define, les types d'argument sont contrôlés, et les conversions nécessaires sont exécutées correctement.
Les macros #define sont mauvaises pour votre santé; ne les utilisez pas à moins d'y être contraint.
[ Haut | Bas | Rechercher ]
void f(int i, char c);
Mais quand vous définissez une fonction inline, vous ajoutez au début de la définition de la fonction le mot-clé inline, et vous mettez la définition dans le fichier d'en-tête:
inline void f(int i, char c) { ... }
Note: Il est impératif que la définition de la fonction (la partie entre {...}) soit placé dans un fichier d'en-tête, à moins que la fonction soit utilisée seulement dans ce seul fichier .cpp. En particulier, si vous mettiez inline la définition de la fonction dans un fichier cpp et vous l'appeliez d'un autre fichier, vous obtiendriez "une erreur externe" (fonction non définie) au moment de l'édition de liens.
[ Haut | Bas | Rechercher ]
class Fred { public: void f(int i, char c); };
Mais quand vous définissez une fonction membre inline, vous ajoutez au début de la définition de la fonction membre le mot-clé inline, et vous mettez la définition dans un fichier d'en-tête:
inline void Fred::f(int i, char c) { ... }
Il est habituellement impératif que la définition de la fonction (la partie entre {...}) soit placé dans un fichier d'en-tête. Si vous mettiez inline la définition d'une fonction dans un fichier d'implémentation cpp, et si cette fonction était appellée d'un autre fichier cpp, vous obtiendriez "une erreur externe" (fonction non définie) au moment de l'édition de liens.
[ Haut | Bas | Rechercher ]
class Fred { public: void f(int i, char c) { ... } };
Bien que ce soit plus facile pour la personne qui écrit la classe, c'est aussi plus dur pour le lecteur puisqu'on mélange "ce que fait" la classe avec "comment elle le fait". En raison de ce mélange, on préfère normalement définir des fonctions de membre en dehors du corps de classe avec le mot-clé inline. Comprenez que dans un monde orienté objet et réutilisation, il y a beaucoup de gens qui utilise la classe, mais une seule personne qui la créé (vous même); c'est pourquoi vous devriez faire les choses en faveurs du plus grand nombre plutôt que pour le plus petit.
[ Haut | Bas | Rechercher ]
Ecrire à l'auteur,
au traducteur,
ou en savoir plus sur la traduction.
C++ FAQ Lite fr |
Table des matières |
Index |
A propos de l'auteur |
© |
Téléchargez votre propre copie ]
Dernière révision Sun Apr 13 23:54:23 PDT 2003