89 votes

statique des variables dans une fonction inline

J'ai une fonction qui est déclarée et définie dans un fichier d'en-tête. C'est un problème par lui-même. Lorsque cette fonction n'est pas incorporé, chaque unité de traduction qui utilise cet en-tête obtient une copie de la fonction, et quand ils sont liés ensemble, nous sont dupliqués. Je "fixe" qu'en faisant de la fonction inline, mais je crains que ce est un fragile de solution parce qu'autant que je sache, le compilateur ne garantit pas l'in-lining, même lorsque vous spécifiez le mot clé "inline". Si ce n'est pas vrai, merci de me corriger.

De toute façon, la vraie question est de savoir ce qui se passe pour les variables statiques à l'intérieur de cette fonction? Le nombre de copies à faire, je me retrouve avec?

112voto

paercebal Points 38526

Je suppose que vous avez raté quelque chose, ici.

statique?

La déclaration d'une fonction statique de se faire "caché" dans son unité de compilation. Si vous déclarez des fonctions statiques dans un en-tête, alors toutes les unités de compilation, y compris cet en-tête ont leur propre copie de la fonction (et, éventuellement, des variables statiques à l'intérieur).

Cela signifie que si vous avez une fonction statique (ou même un objet global/variable), alors cette fonction existe dans chaque unité de compilation (c'est à dire un fichier CPP) qui inclut l'en-tête où cette fonction statique est déclarée. Je n'ai pas encore de voir des cas (mais quelques rares debug coin des cas) où c'est quelque chose que vous voulez.

inline?

Déclarant inline en fait un candidat pour inline (il ne signifie pas grand-chose de nos jours en C++, le compilateur en ligne ou pas, parfois, en ignorant le fait que le mot-clé inline est présent ou absent).

Dans un en-tête, elle a un effet secondaire: La fonction inline peut être défini plusieurs fois dans le même module, et l'éditeur de liens il vous suffit de rejoindre le "eux" en un seul (si elles n'ont pas été intégrées pour le compilateur de la raison).

Ceci a l'avantage de "statique" (c'est à dire qu'il peut être défini dans un en-tête) sans ses défauts (il existe au plus une fois, si il n'est pas incorporé)

statique + inline?

Mixage en ligne et statique aura alors les conséquences que vous avez décrit (même si la fonction est insérée, la variable statique à l'intérieur ne sera pas, et vous vous retrouverez avec autant de variables statiques comme vous l'avez unités de compilation, y compris la définition de vos fonctions statiques).

De toute façon, quel est le point de déclarer votre fonction statique en C++?

Parce qu'il devrait être privé? Si si, ne pas la déclarer dans un en-tête (seulement dans un RPC), ou mieux encore, utiliser C++idiome pour que (la définir à l'intérieur d'un anonyme, un espace de noms à l'intérieur du fichier CPP).

(Notez que je parle de fonctions, pas de méthodes: les méthodes statiques ont leurs usages en C++)

Réponse de l'auteur, la question de savoir

Depuis que j'ai écrit la question que je l'ai essayé avec Visual Studio 2008. J'ai essayé d'activer toutes les options qui font de VS agir en conformité avec les normes, mais il est possible que j'ai raté quelques. Ce sont les résultats:

Lorsque la fonction est simplement "inline", il n'y a qu'une seule copie de la variable statique.

Lorsque la fonction est "static inline", il y a autant d'exemplaires qu'il y a des unités de traduction.

La vraie question est maintenant de savoir si les choses sont censé être de cette façon, ou si c'est une idiosyncrasie de le compilateur C++ de Microsoft.

Donc je suppose que vous avez quelque chose comme ça:

void doSomething()
{
   static int value ;
}

Vous devez réaliser que la variable statique à l'intérieur de la fonction, il suffit de mettre, une variable globale caché de tous, mais la fonction de la portée, ce qui signifie que seule la fonction à laquelle elle est déclarée à l'intérieur peut atteindre.

Inlining la fonction ne change rien:

inline void doSomething()
{
   static int value ;
}

Il n'y aura qu'une variable globale masquée. Le fait que le compilateur va essayer d'insérer le code ne change pas le fait il n'existe qu'une seule variable cachée.

Maintenant, si votre fonction est déclarée statique:

static void doSomething()
{
   static int value ;
}

Ensuite, il est "privé" pour chaque unité de compilation, ce qui signifie que chaque fichier CPP, y compris l'en-tête où la fonction statique est déclaré aura sa propre copie privée de la fonction, y compris sa propre copie privée de global variable cachée, donc autant de variables qu'il y a des unités de compilation, y compris l'en-tête.

L'ajout de "en ligne" à "statique" de la fonction avec un "statique" de la variable à l'intérieur:

inline static void doSomething()
{
   static int value ;
}

a le même résultat que de ne pas l'ajout de cette mot clé "inline", autant que la variable statique à l'intérieur est concerné.

Ainsi, le comportement de VC++ est correcte, et que vous êtes se méprendre sur le sens réel de "inline" et "statique".

42voto

Mark Ransom Points 132545

Je crois que le compilateur crée de nombreuses copies de la variable, mais l'éditeur de liens en choisit un et rend tous les autres, référence. J'ai eu des résultats similaires quand j'ai tenté l'expérience de créer différentes versions d'une fonction inline; si la fonction n'était pas réellement inline (mode debug), tous les appels sont allés à la même fonction, quel que soit le fichier source, ils ont été appelés à partir.

Penser comme un compilateur pour un instant - comment pourrait-il en être autrement? Chaque unité de compilation (fichier source) est indépendant des autres, et peuvent être compilés séparément; chacun doit donc créer une copie de la variable, en pensant qu'il est le seul. L'éditeur de liens a la capacité d'atteindre à travers ces frontières et ajuster les références pour les deux variables et de fonctions.

P. S. Si vous pensez que j'ai tort, laissez un commentaire et permettez-moi d'apprendre quelque chose. Je suis fatigué de anonyme downvotes.

13voto

Matt Points 51

J'ai trouvé la Marque Rançon de la réponse et des conseils pour que le compilateur crée de nombreuses copies de la variable statique, mais l'éditeur de liens choisit et applique à travers toutes les unités de traduction.

D'ailleurs, j'ai trouvé ceci:

Voir [dcl.fct.spec]/4:

"[..] Une fonction en ligne, avec une liaison externe doit avoir le même adresse à toutes les unités de traduction. Une variable locale statique dans un extern fonction en ligne correspond toujours à la même objet. Un littéral de chaîne dans un extern inline de la fonction est le même objet dans les différentes unités de traduction."

Je n'ai pas de copie de la norme pour vérifier, mais il correspond à mon expérience de l'examen de l'assemblée en VS Express 2008

5voto

C'est censé être de cette façon. "statique" indique au compilateur que vous voulez de la fonction est locale à l'unité de compilation, donc vous voulez une copie par unité de compilation et d'une copie des variables statiques par exemple de la fonction.

"inline", utilisé pour indiquer au compilateur que la fonction est insérée; de nos jours, il suffit juste d'elle que "c'est ok si il y a plusieurs copies du code, assurez-vous juste que c'est la même fonction". Si tout le monde partage les variables statiques.

Note: cette réponse a été écrite en réponse à la réponse de l'affiche originale posté à lui-même.

3voto

Marvin Points 732

Depuis que j'ai écrit la question que je l'ai essayé avec Visual Studio 2008. J'ai essayé d'activer toutes les options qui font de VS agir en conformité avec les normes, mais il est possible que j'ai raté quelques. Ce sont les résultats:

Lorsque la fonction est simplement "inline", il n'y a qu'une seule copie de la variable statique.

Lorsque la fonction est "static inline", il y a autant d'exemplaires qu'il y a des unités de traduction.

La vraie question est maintenant de savoir si les choses sont censé être de cette façon, ou si c'est un ideosyncracy de le compilateur C++ de Microsoft.

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