Maison  >  Article  >  développement back-end  >  Fonctions en ligne en C et C++

Fonctions en ligne en C et C++

PHPz
PHPzoriginal
2024-09-09 10:33:46690parcourir

Inline Functions in C and C++

Introduction

C++ a ajouté le mot-clé inline qui peut préfixer une définition de fonction, tel que :

inline int max_int( int a, int b ) {
    return a > b ? a : b;
}

pour donner au compilateur un « indice » selon lequel le programme dans son ensemble pourrait bénéficier en termes de performances de la fonction étant inline.

Une fonction qui a été inline a vu son code étendu à chaque fois qu'elle a été appelée plutôt que d'exécuter le mécanisme normal d'appel de fonction de :

  • Sauvegarde des registres.
  • Pousser les valeurs des arguments sur la pile.
  • Exécution de l'instruction d'appel.
  • La fonction exécutant finalement l'instruction ret.
  • Restauration des registres.

Pour les très petites fonctions, l'inline peut générer un gain de performances. Mais comme pour presque tout le reste, il y a des compromis à faire.

Le mot-clé en ligne a été rétroporté vers C99, mais avec des exigences légèrement différentes – nous en reparlerons plus tard.

Différences avec les macros

Les fonctions en ligne sont comme (et sont destinées à remplacer de nombreuses utilisations) des macros de type fonction. Généralement, c'est une bonne chose car les fonctions en ligne sont des fonctions et ont une sémantique complète des fonctions plutôt qu'une simple substitution de texte effectuée par le préprocesseur qui ne comprend ni le C ni le C++.

Une macro naïvement équivalente à la fonction max_int() :

#define MAX_INT(A,B)  A > B ? A : B  /* bad implementation */

a les problèmes suivants :

  • Les arguments développés, par exemple MAX(n & 0xFF, 8), peuvent entraîner une mauvaise priorité des opérateurs.
  • Les arguments ayant des effets secondaires, par exemple MAX(n++, 8), peuvent avoir plusieurs effets secondaires.
  • Il n'y a pas de vérification de type des arguments lors de la définition.
  • Les erreurs sont souvent verbeuses et difficiles à lire.

En plus, une macro :

  • Peut modifier son argument (ce qui souvent pas ce que vous voulez).

Les fonctions en ligne ne présentent aucun de ces problèmes et peuvent pourtant offrir le même avantage en termes de performances. Par conséquent, utilisez des fonctions en ligne au lieu de macros de type fonction.

Seulement un indice

Comme mentionné, spécifier inline est seulement un « indice » pour le compilateur selon lequel le programme dans son ensemble pourrait bénéficier en termes de performances de la fonction inline. Le compilateur est libre d'ignorer l'indice.

Pourquoi ? Parce qu’il y a des cas où ce n’est pas une bonne idée, voire impossible. Une fonction n'est pas intégrée ou n'est généralement pas intégrée lorsque l'un des éléments suivants est vrai :

  • La fonction est « trop grande ».
  • Vous appelez la fonction via un pointeur vers une fonction.
  • La fonction est récursive.
  • La fonction a une boucle.

Il peut y avoir d'autres raisons. Tout dépend fortement de la fonction, de ses arguments, du compilateur et des options qui lui sont proposées.

Si le compilateur ne peut pas ou choisit de ne pas intégrer une fonction, il ne pas vous avertit qu'il ne l'a pas fait (par défaut). Certains compilateurs, par exemple gcc, ont une option -Winline qui vous avertira et vous indiquera la raison pour laquelle une fonction n'a pas été intégrée.

La spécification en ligne est similaire à l'ancien code spécifiant le registre : ce ne sont que des indices.

Quand (et quand pas) mettre en ligne

Pour la plupart des fonctions, l’essentiel du coût d’exécution de la fonction réside dans le corps de la fonction, et non dans le mécanisme d’appel de fonction. Par conséquent, pour qu’une fonction soit un bon candidat pour l’inline, elle doit généralement être :

  • Assez petit pour que le coût du mécanisme d'appel de fonction domine.
  • Utilisé dans les endroits où la performance compte réellement, par exemple dans les boucles serrées.

En cas de doute, profilez votre code. L'utilisation en ligne n'est pas un mot-clé magique « rendez-moi plus rapide ». De plus, une utilisation excessive de l'inline peut entraîner une surcharge du code qui aggrave en outre les performances de votre programme pire dans l'ensemble.

Pour en savoir plus, voir La maladie en ligne.

Les fonctions qui sont souvent de bons candidats pour l'inline incluent :

  • Les « one-liners » tels que les « getters » et les « setters ».
  • Des wrappers simples autour des appels à d'autres fonctions qui fournissent des valeurs spécifiques pour les arguments ou effectuent des conversions.

Une fonction en ligne idéale à la fois augmente les performances et diminue la taille du code.

Cependant, une mise en garde pour toute fonction en ligne est que si sa définition change, elle nécessitera de recompiler tout le code qui l'utilise.

Optimisations en ligne

Si une fonction en ligne est réellement intégrée par le compilateur, alors, en plus d'élider le code du mécanisme normal d'appel de fonction, le compilateur peut également être capable de :

  • Eliminate one or more function arguments completely whose values are constants via immediate addressing.
  • Perform better optimizations spanning the code the function is inlined into that it normally couldn’t perform across function boundaries.

Inline Function Definition

In order for the compiler to be able to inline a function, it has to be able to “see” its definition (not just its declaration) in every .c or .cpp file it’s used in just like a macro. Hence, an inline function must be defined in a header file.

Normally, a function, like everything else, must have exactly one definition by adhering to the one definition rule (ODR). However, since the definition of an inline function is “seen” in multiple .c or .cpp files, the ODR is suspended for that function.

It is possible to have different definitions for inline functions having the same name, but this results in undefined behavior since the compiler has no way to check that every definition is the same.

To inline a function in C++, all you need do is prefix the function definition with inline — that’s it. The compiler and/or linker will automatically discard all but one definition from the final executable file for you.

However, to inline a function in C, you additionally must explicitly tell the compiler into what .o file to put the one definition in the event the compiler is either unable or unwilling to inline a function via extern inline.

For example, in exactly one .c file, you would declare a function like:

// util.c
extern inline int max_int( int, int );

That tells the compiler to “put the one definition for max_int() into util.o.”

Alternatively in C, you can instead declare an inline function static also:

static inline int max_int( int a, int b ) {
    return a > b ? a : b;
}

If you do this, then:

  • You do not have to declare a function extern inline anywhere.
  • However, if the compiler doesn’t inline a function, it will generate a definition in every .c file it’s included into again leading to code bloat.
  • If the function has any static local variables, every definition will have distinct copies (that may or may not be what you want).

Conclusion

Inline functions, if used judiciously, can yield performance gains. Generally, only very small functions are good candidates for inlining.

Starting in C++11, inline functions can alternatively be declared constexpr, but that’s a story for another time.

References

  • Linux kernel coding style, §15 The inline disease.
  • Myth and reality about inline in C99.
  • The Annotated C++ Reference Manual, Margaret A. Ellis & Bjarne Stroustrup, Addison-Wesley, 1990, ISBN 0-201-51459-1, §7.1.2 Function Specifiers, pp. 99–105.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn