85 votes

Ne faut-il jamais utiliser de fonction statique en ligne ?

L'utilisation de l'option inline mot-clé (§ 7.1.3/4) :

  1. Il indices le compilateur que la substitution du corps de la fonction au point d'appel est préférable au mécanisme habituel d'appel de fonction.
  2. Même si la substitution en ligne est omise, les autres règles (notamment en ce qui concerne les Règle de la définition unique ) pour la mise en ligne sont suivies.

En général, tout compilateur classique substitue le corps de la fonction au point d'appel si nécessaire, de sorte que le marquage de la fonction inline simplement pour #1 n'est pas vraiment nécessaire.

Plus loin #2 Si j'ai bien compris, lorsque vous déclarez une fonction en tant que static inline fonction,

En static sur la fonction force le mot-clé inline pour avoir un lien interne ( les fonctions en ligne ont un lien externe ) Chaque instance d'une telle fonction est traitée comme une fonction distincte( l'adresse de chaque fonction est différente ) et chaque instance de ces fonctions possède sa propre copie des variables locales statiques et des chaînes de caractères littérales ( une fonction inline n'a qu'une seule copie de ces éléments )

Une telle fonction se comporte donc comme n'importe quelle autre fonction static et le mot-clé inline n'a plus d'importance, il devient redondant.

Ainsi, le marquage pratique d'une fonction static y inline les deux n'ont aucune utilité. Il faut soit static ( pas le plus préféré ) ou inline ( la plus préférée ),
Ainsi, l'utilisation de static y inline ensemble sur une fonction pratiquement inutile ?

69voto

Potatoswatter Points 70305

Votre analyse est correcte, mais n'implique pas nécessairement l'inutilité. Même si la plupart des compilateurs intègrent automatiquement les fonctions (raison n° 1), il est préférable de déclarer inline juste pour décrire l'intention.

Ne pas tenir compte de l'interaction avec inline , static doivent être utilisées avec parcimonie. Les fonctions static à la portée de l'espace de noms était auparavant déprécié en faveur des espaces de noms non nommés (C++03 §D.2). Pour une raison obscure dont je ne me souviens pas, il a été retiré de la dépréciation en C++11, mais vous devriez rarement en avoir besoin.

En pratique, marquer une fonction comme statique ou en ligne n'a donc aucune utilité. Elle doit être soit statique (ce qui n'est pas la meilleure solution), soit en ligne (ce qui est la meilleure solution),

Il n'y a pas de notion de préférence. static implique que des fonctions différentes ayant la même signature peuvent exister dans des systèmes différents. .cpp (unités de traduction). inline sans static signifie qu'il est acceptable que différentes unités de traduction définissent la même fonction avec des définitions identiques.

Ce qu'il faut faire est Il est préférable d'utiliser un espace de noms sans nom au lieu de static :

namespace {
    inline void better(); // give the function a unique name
}

static inline void worse(); // kludge the linker to allowing duplicates

29voto

Suma Points 11966

Les termes "statique" et "en ligne" sont orthogonaux (indépendants). Static signifie que la fonction ne doit pas être visible en dehors de l'unité de traduction, inline est une indication au compilateur que le programmeur souhaite que cette fonction soit intégrée. Ces deux notions ne sont pas liées.

Utilisation static inline a du sens lorsque la fonction intégrée n'est pas utilisée en dehors de l'unité de traduction. En l'utilisant, vous pouvez éviter une violation accidentelle de la règle ODR en nommant une autre fonction intégrée dans une autre unité de traduction avec le même nom.

Exemple :

source1.cpp :

inline int Foo()
{
  return 1;
}

int Bar1()
{
  return Foo();
}

source2.cpp :

inline int Foo()
{
  return 2;
}

int Bar2()
{
  return Foo();
}

Sans utiliser static sur Foo (ou sans utiliser un espace de noms anonyme, ce qui est la méthode préférée de la plupart des programmeurs C++), cet exemple viole l'ODR et les résultats sont indéfinis. Vous pouvez tester avec Visual Studio le résultat de Bar1/Bar2 en fonction des paramètres du compilateur - dans la configuration Debug, Bar1 et Bar2 renverront la même valeur (inlining non utilisé, une implémentation choisie aléatoirement par le linker), dans la configuration Release, chacun d'entre eux renverra la valeur prévue.

18voto

dividebyzero Points 408

Je n'ai peut-être pas tout à fait raison, mais pour autant que je sache, déclarer une fonction static inline est le seul moyen de permettre au compilateur de générer un code machine dans lequel la fonction n'est pas du tout définie dans le code compilé, et tout ce que vous avez est une substitution directe de l'appel de fonction dans une séquence d'instructions, comme s'il s'agissait d'un corps de procédure ordinaire, sans aucune trace dans le code machine d'un appel de procédure relatif à la définition de la fonction dans le code source.

En d'autres termes, ce n'est qu'avec static inline vous pouvez vraiment remplacer l'utilisation d'une macro, inline ne suffit pas.

Une simple recherche sur Google pour "static inline" vous montrera les pages de documentation du compilateur qui en parlent. Je pense que cela devrait suffire pour répondre à votre question, et dire "non, ce n'est pas pratiquement inutile". Voici un exemple de site discutant de l'utilisation de inline et plus particulièrement de static inline http://www.greenend.org.uk/rjk/tech/inline.html

13voto

iammilind Points 29275

Si vous parlez de gratuit fonctions ( namespace ), votre hypothèse est correcte. static inline n'ont en effet pas beaucoup de valeur. En effet, les fonctions n'ont pas beaucoup de valeur. static inline est simplement un static qui satisfait automatiquement à l'ODR et à la inline est redondant pour les besoins de l'ODR.

Cependant, lorsque nous parlons de membre méthodes ( class ), le static inline a une valeur.
Une fois que vous avez déclaré un class comme inline Le corps de l'article doit être visible par toutes les unités de traduction, y compris celle de l'article. class .

Rappelez-vous que static Le mot-clé a une signification différente lorsqu'il s'agit d'une class .
Editer : Comme vous le savez peut-être, le static à l'intérieur d'un class n'a pas de lien interne, en d'autres termes une classe ne peut pas avoir plusieurs copies de son static en fonction des unités de traduction (.cpp) .
Mais un static fonction à namespace /global scope a des copies différentes pour chaque unité de traduction.

par exemple

// file.h
static void foo () {}
struct A {
  static void foo () {}
};

// file1.cpp
#include"file.h"
void x1 ()
{
  foo();  // different function exclusive to file1.cpp
  A::foo();  // same function
}

// file2.cpp
#include"file.h"
void x2 ()
{
  foo();  // different function exclusive to file2.cpp
  A::foo();  // same function
}

3voto

Luke Small Points 31

Je viens de lire une page de manuel pour gcc et elle mentionne spécifiquement l'utilisation de static inline avec un drapeau de compilateur. Dans le cas de l'indicateur, la fonction est intégrée et si elle est également statique et intégrée à chaque fois qu'elle est appelée, alors elle se débarrasse de la définition de la fonction qui ne sera jamais utilisée dans le fichier objet créé, réduisant ainsi la taille du code généré d'un tout petit peu.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X