L'utilisation du mot clé inline
(§ 7.1.3/4) a deux implications:
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?
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
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.
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 inline
http://www.greenend.org.uk/rjk/tech/inline.html
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
}
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.