web-dev-qa-db-fra.com

Ne devrait-on jamais utiliser une fonction inline statique?

L'utilisation du mot clé inline (§ 7.1.3/4) a deux implications:

  1. Le astuces indique au compilateur que la substitution du corps de la fonction au point d’appel est préférable au mécanisme d’appel habituel de la fonction.
  2. Même si la substitution en ligne est omise, les autres règles (en particulier w.r.t règle de définition unique) pour les procédures en ligne sont suivies.

Habituellement, tout compilateur traditionnel remplacera le corps de la fonction au point d’appel si nécessaire, donc marquer la fonction inline simplement pour #1 n'est pas vraiment nécessaire.

Plus loin w.r.t #2, Si je comprends bien, lorsque vous déclarez une fonction en tant que static inline une fonction,

Le mot clé static de la fonction force la fonction inline à disposer d'un lien interne (les fonctions inline ont un lien externe) Chaque instance d'une telle fonction est traitée comme une entité distincte. function (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 littéraux de chaîne (ne fonction en ligne n'en a qu'une copie )

Ainsi, une telle fonction agit comme n'importe quelle autre fonction static et le mot clé inline n'a plus d'importance, il devient redondant.

Donc, marquer pratiquement une fonction static et inline n'a aucune utilité. Soit static (pas préféré) ou inline (préféré),
Donc, utiliser static et inline ensemble sur une fonction pratiquement inutile?

58
Alok Save

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

Ne pas tenir compte des interactions avec les fonctions inline, static doit être utilisé avec parcimonie. Le modificateur static au niveau de l'espace de noms était auparavant déconseillé au profit d'espaces de noms non nommés (C++ 03 §D.2). Pour des raisons obscures dont je ne me souviens pas, il a été supprimé de la dépréciation de C++ 11, mais vous devriez rarement en avoir besoin.

Ainsi, le marquage pratique d’une fonction statique et inline n’a aucune utilité. Soit il devrait être statique (pas le plus préféré) ou en ligne (le plus préféré),

Il n'y a pas de notion de préférence. static implique que différentes fonctions avec la même signature peuvent exister dans différentes .cpp fichiers (unités de traduction). inline sans static signifie que différentes unités de traduction peuvent définir la même fonction avec des définitions identiques.

Ce que is préfère, c’est utiliser un espace de nom non nommé à la place de static:

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

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

Static et inline sont orthogonaux (indépendants). Statique signifie que la fonction ne doit pas être visible en dehors de l'unité de traduction; inline est un indice pour le compilateur que le programmeur souhaite que cette fonction soit en ligne. Ces deux ne sont pas liés.

En utilisant static inline est logique lorsque la fonction en ligne 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 du 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 recommandé par la plupart des programmeurs C++), cet exemple viole l'ODR et les résultats ne sont pas définis. Vous pouvez tester avec Visual Studio le résultat de Bar1/Bar2 dépendra des paramètres du compilateur - dans la configuration de débogage, Bar1 et Bar2 renverront la même valeur (inlining non utilisé, une implémentation sélectionnée aléatoirement par l'éditeur de liens), dans la configuration de publication chacun d'eux. retournera la valeur souhaitée.

23
Suma

Je n’ai peut-être pas tout à fait raison à ce sujet, mais pour autant que je sache, déclarer une fonction static inline est le seul moyen de faire (ou de permettre) au compilateur de générer un code machine où la fonction n'est vraiment pas définie dans le code compilé, et tout ce que vous avez à faire est une substitution directe de la fonction déclarée dans une séquence d'instructions , comme si c’était juste un corps de procédure ordinaire, sans trace dans le code machine d’un appel de procédure relatif à cette définition de fonction à partir du code source.

C'est-à-dire qu'avec static inline vous pouvez vraiment remplacer l’utilisation d’une macro, inline n’est pas suffisant en soi.

Une simple recherche Google "statique en ligne" vous montrera les pages de documentation du compilateur qui en parlent. Je suppose que cela devrait suffire à répondre à votre question et à dire: "Non, ce n'est pas pratiquement inutile". Voici un exemple de site traitant de l’utilisation de inline et plus précisément de static inlinehttp://www.greenend.org.uk/rjk/tech/inline.html

13
dividebyzero

Si vous parlez de fonctions gratuites (namespace scope), votre hypothèse est correcte. static inline _ les fonctions n’ont en effet pas beaucoup de valeur. Alors static inline est simplement une fonction static, qui satisfait automatiquement l’ODR et inline est redondante aux fins de l’ODR.

Cependant, lorsque nous parlons de méthodes membre (class scope), le static inline fonction a la valeur.
Une fois que vous déclarez une méthode class en tant que inline, son corps complet doit être visible par toutes les unités de traduction, ce qui inclut ce préfixe class.

Rappelez-vous que le mot clé static a une signification différente lorsqu'il s'agit d'un class.
Edit: Comme vous le savez peut-être, static fonctionne dans un class ne possède pas de lien interne, autrement dit Une classe ne peut pas avoir différentes copies de sa méthode static en fonction des unités de traduction (.cpp) .
Mais une fonction gratuite static à namespace/global 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
}
10
iammilind

Je viens de lire une page de manuel pour gcc qui indique spécifiquement l’utilisation d’inline statique avec un drapeau de compilation. Dans le cas du drapeau, il insère la fonction. S'il est également statique et est inséré dans toutes les instances appelées, il supprime 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é par ce petit peu.

1
Luke Small