Le mot clé static
- est celui qui a plusieurs significations en C ++ que je trouve très déroutant et je ne peux jamais penser à comment il est censé fonctionner.
D'après ce que je comprends, il y a static
la durée de stockage, ce qui signifie qu'elle dure toute la durée de vie du programme dans le cas d'un global, mais lorsque vous parlez d'un local, cela signifie que c'est zéro initialisé par défaut.
La norme C ++ dit ceci pour les membres de données de classe avec le mot-clé static
:
3.7.1 Durée de stockage statique [basic.stc.static]
3 Le mot-clé statique peut être utilisé pour déclarer une variable locale avec une durée de stockage statique.
4 Le mot clé static appliqué à un membre de données de classe dans une définition de classe donne la durée de stockage statique du membre de données.
Qu'est-ce que cela signifie avec une variable locale ? Est-ce une variable locale de fonction? Parce qu'il y a aussi que lorsque vous déclarez une fonction locale commestatic
elle n'est initialisée qu'une seule fois, la première fois qu'elle entre dans cette fonction.
Il ne parle également que de la durée de stockage en ce qui concerne les membres de la classe, qu'en est-il non spécifique à l'instance, c'est également une propriété de static
non? Ou est-ce la durée de stockage?
Maintenant, qu'en est-il du cas static
et de la portée du fichier? Toutes les variables globales sont-elles considérées comme ayant une durée de stockage statique par défaut? Ce qui suit (extrait de la section 3.7.1) semble l'indiquer:
1 Toutes les variables qui n'ont pas de durée de stockage dynamique, n'ont pas de durée de stockage de thread et ne sont pas locales ont une durée de stockage statique. Le stockage de ces entités doit durer pendant la durée du programme (3.6.2, 3.6.3)
Quel est le static
lien avec le couplage d'une variable?
Tout ce static
mot-clé est carrément déroutant, quelqu'un peut-il clarifier les différentes utilisations de l'anglais et me dire quand initialiser un static
membre de la classe?
Réponses:
Variables:
static
des variables existent pour la "durée de vie" de l' unité de traduction dans laquelle elle est définie , et:constexpr
. Autre chose, et vous vous retrouvez avec une variable distincte dans chaque unité de traduction, ce qui est complètement déroutant)static
, mais peuvent être adressés à partir de la classe ainsi que d'une instance (commestd::string::npos
). [Remarque: vous pouvez déclarer des membres statiques dans une classe, mais ils doivent généralement être définis dans une unité de traduction (fichier cpp), et en tant que tel, il n'y en a qu'un par classe]emplacements comme code:
Avant l'
main
exécution de toute fonction dans une unité de traduction (éventuellement après le début de l'exécution), les variables avec une durée de stockage statique (étendue de l'espace de noms) dans cette unité de traduction seront "constamment initialisées" (dans la mesure duconstexpr
possible, ou zéro sinon), puis non les sections locales sont «initialisées dynamiquement» correctement dans l'ordre dansstd::string="HI";
lequel elles sont définies dans l'unité de traduction (pour des choses comme cela ne le sont pasconstexpr
). Enfin, les statiques fonctionnelles locales seront initialisées la première fois que l'exécution "atteint" la ligne où elles sont déclarées. Toutes lesstatic
variables sont toutes détruites dans l'ordre inverse de l'initialisation.Le moyen le plus simple pour obtenir tout cela est de faire en sorte que toutes les variables statiques qui ne sont pas
constexpr
initialisées en fonction locals statiques, ce qui garantit que toutes vos statistiques / globales sont initialisées correctement lorsque vous essayez de les utiliser quoi qu'il arrive, empêchant ainsi l' initialisation statique commander le fiasco .Soyez prudent, car lorsque la spécification indique que les variables de portée d'espace de noms ont par défaut "durée de stockage statique", elles signifient le bit "durée de vie de l'unité de traduction", mais cela ne signifie pas qu'il ne peut pas être consulté en dehors du fichier.
Les fonctions
Significativement plus simple,
static
est souvent utilisé comme fonction de membre de classe, et très rarement utilisé pour une fonction autonome.Une fonction membre statique diffère d'une fonction membre régulière en ce qu'elle peut être appelée sans instance d'une classe, et comme elle n'a pas d'instance, elle ne peut pas accéder aux membres non statiques de la classe. Les variables statiques sont utiles lorsque vous souhaitez avoir une fonction pour une classe qui ne fait absolument référence à aucun membre d'instance ou pour gérer
static
les variables de membre.Une
static
fonction libre signifie que la fonction ne sera référencée par aucune autre unité de traduction, et donc l'éditeur de liens peut l'ignorer complètement. Cela a un petit nombre d'objectifs:static void log(const char*) {}
dans chaque fichier cpp, et ils peuvent tous se connecter de manière différente.la source
classname::
portée. Les fonctions membres de classe statiques sont comme des fonctions globales mais étendues à la classe, ou comme des membres normaux mais sansthis
(ce n'est pas un choix - ces deux devraient être équivalents).namespace A { static int x; }
, ce qui signifie un lien interne et est très différent du comportement des membres de données de classe statiques .La durée de stockage statique signifie que la variable réside au même endroit en mémoire pendant toute la durée de vie du programme.
Le lien est orthogonal à cela.
Je pense que c'est la distinction la plus importante que vous puissiez faire. Comprendre cela et le reste, ainsi que s'en souvenir, devrait être facile (ne pas s'adresser directement à @Tony, mais à quiconque pourrait le lire à l'avenir).
Le mot-clé
static
peut être utilisé pour désigner la liaison interne et le stockage statique, mais en substance, ils sont différents.Oui. Quel que soit le moment où la variable est initialisée (lors du premier appel à la fonction et lorsque le chemin d'exécution atteint le point de déclaration), elle résidera au même endroit en mémoire pendant toute la durée de vie du programme. Dans ce cas,
static
lui donne un stockage statique.Oui, tous les globaux ont par définition une durée de stockage statique (maintenant que nous avons clarifié ce que cela signifie). Mais les variables de portée d'espace de noms ne sont pas déclarées avec
static
, car cela leur donnerait un lien interne, donc une variable par unité de traduction.Il fournit un lien interne aux variables de portée d'espace de noms. Il donne aux membres et aux variables locales une durée de stockage statique.
Développons tout cela:
Certainement, à moins que vous ne le connaissiez. :) Essayant d'éviter d'ajouter de nouveaux mots clés à la langue, le comité a réutilisé celui-ci, l'OMI, à cet effet - confusion. Il est utilisé pour signifier différentes choses (pourrais-je dire, probablement des choses opposées).
la source
static int x
à la portée de l'espace de noms, cela lui donne un stockage non statique ?Afin de clarifier la question, je préfère classer l'utilisation du mot-clé «statique» sous trois formes différentes:
(UNE). les variables
(B). les fonctions
(C). Variables membres / fonctions des classes
l'explication ci-dessous pour chacune des sous-rubriques:
(A) mot-clé 'statique' pour les variables
Celui-ci peut être peu délicat, mais s'il est expliqué et compris correctement, il est assez simple.
Pour expliquer cela, il est d'abord très utile de connaître la portée, la durée et le lien des variables, sans lesquelles les choses sont toujours difficiles à voir à travers le concept trouble du mot-clé staic
1. Portée : détermine où dans le fichier, la variable est accessible. Il peut être de deux types: (i) Portée locale ou étendue . (ii) Portée mondiale
2. Durée : détermine quand une variable est créée et détruite. Encore une fois, il est de deux types: (i) Durée de stockage automatique (pour les variables ayant une portée locale ou bloc). (ii) Durée de stockage statique (pour les variables ayant une portée globale ou des variables locales (dans une fonction ou dans un bloc de code) avec spécificateur statique ).
3. Lien : détermine si une variable est accessible (ou liée) dans un autre fichier. Encore une fois (et heureusement), il est de deux types: (i) Liaison interne (pour les variables ayant une portée de bloc et une portée globale / portée de fichier / portée globale de l'espace de noms) (ii) Liaison externe (pour les variables n'ayant qu'une portée globale / portée de fichier / Portée de l'espace de noms global)
Voyons un exemple ci-dessous pour une meilleure compréhension des variables globales et locales simples (pas de variables locales avec une durée de stockage statique):
Maintenant vient le concept de Linkage. Lorsqu'une variable globale définie dans un fichier est destinée à être utilisée dans un autre fichier, le lien de la variable joue un rôle important.
Le couplage des variables globales est spécifié par les mots clés: (i) statique , et, (ii) extern
(Maintenant, vous obtenez l'explication)
un mot-clé statique peut être appliqué à des variables de portée locale et globale, et dans les deux cas, elles signifient des choses différentes. J'expliquerai d'abord l'utilisation du mot-clé «statique» dans les variables à portée globale (où je clarifie également l'utilisation du mot-clé «extern») et ensuite pour celles à portée locale.
1. Mot-clé statique pour les variables de portée globale
Les variables globales ont une durée statique, ce qui signifie qu'elles ne sortent pas du champ d'application lorsqu'un bloc de code particulier (par exemple, main ()) dans lequel il est utilisé se termine. Selon le lien, ils sont accessibles uniquement dans le même fichier où ils sont déclarés (pour la variable globale statique), ou en dehors du fichier même en dehors du fichier dans lequel ils sont déclarés (variables globales de type externe)
Dans le cas d'une variable globale ayant un spécificateur externe, et si cette variable est accessible en dehors du fichier dans lequel elle a été initialisée, elle doit être déclarée en avant dans le fichier où elle est utilisée, tout comme une fonction doit être en avant déclaré si sa définition se trouve dans un fichier différent de celui où elle est utilisée.
En revanche, si la variable globale a un mot-clé statique, elle ne peut pas être utilisée dans un fichier en dehors duquel elle a été déclarée.
(voir l'exemple ci-dessous pour des éclaircissements)
par exemple:
main3.cpp
maintenant, toute variable en c ++ peut être soit un const, soit un non-const et pour chaque 'const-ness' nous obtenons deux cas de liaison c ++ par défaut, au cas où aucun n'est spécifié:
(i) Si une variable globale est non-const, son lien est extern par défaut , c'est-à-dire que la variable globale non-const est accessible dans un autre fichier .cpp par déclaration directe à l'aide du mot-clé extern (en d'autres termes, non const global les variables ont un lien externe (avec une durée statique bien sûr)). L'utilisation du mot-clé extern dans le fichier d'origine où il a été défini est également redondante. Dans ce cas, pour rendre une variable globale non const inaccessible au fichier externe, utilisez le spécificateur «statique» avant le type de la variable .
(ii) Si une variable globale est const, son lien est statique par défaut , c'est-à-dire qu'une variable globale const n'est pas accessible dans un fichier autre que celui où elle est définie, (en d'autres termes, les variables globales const ont un lien interne (avec une durée statique) bien sûr)). L'utilisation d'un mot-clé statique pour empêcher l'accès à une variable globale const dans un autre fichier est également redondante. Ici, pour faire en sorte qu'une variable globale const ait un lien externe, utilisez le spécificateur 'extern' avant le type de la variable
Voici un résumé des variables de portée globale avec divers liens
Ensuite, nous étudions le comportement des variables globales ci-dessus lorsqu'elles sont accessibles dans un fichier différent.
2. Mot-clé statique pour les variables avec portée locale
Mises à jour (août 2019) du mot clé statique pour les variables de portée locale
Cela peut encore être subdivisé en deux catégories:
(i) mot clé statique pour les variables d'un bloc fonctionnel , et (ii) mot clé statique pour les variables d'un bloc local sans nom.
(i) mot-clé statique pour les variables d'un bloc fonctionnel.
Plus tôt, j'ai mentionné que les variables de portée locale ont une durée automatique, c'est-à-dire qu'elles commencent à exister lorsque le bloc est entré (que ce soit un bloc normal, que ce soit un bloc fonctionnel) et cessent d'exister lorsque le bloc se termine, bref, les variables avec portée locale ont une durée automatique et les variables de durée automatiques (et les objets) n'ont pas de lien, ce qui signifie qu'ils ne sont pas visibles en dehors du bloc de code.
Si un spécificateur statique est appliqué à une variable locale dans un bloc fonctionnel, il modifie la durée de la variable automatique en statique et sa durée de vie est la durée totale du programme, ce qui signifie qu'il a un emplacement de mémoire fixe et que sa valeur est initialisée uniquement une fois avant le démarrage du programme comme mentionné dans la référence cpp (l'initialisation ne doit pas être confondue avec l'affectation)
permet de jeter un oeil à un exemple.
En examinant le critère ci-dessus pour les variables locales statiques et les variables globales statiques, on pourrait être tenté de se demander quelle pourrait être la différence entre elles. Alors que les variables globales sont accessibles à tout moment dans le code (dans la même unité de traduction que dans différentes selon la const -ness et l' extern -ness), une variable statique définie dans un bloc fonction n'est pas directement accessible. La variable doit être renvoyée par la valeur ou la référence de la fonction. Voyons cela par un exemple:
Plus d'explications sur le choix de la variable statique globale et statique locale peuvent être trouvées sur ce thread stackoverflow
(ii) mot-clé statique pour les variables dans un bloc local sans nom.
les variables statiques dans un bloc local (pas un bloc fonctionnel) ne sont pas accessibles en dehors du bloc une fois que le bloc local est hors de portée. Aucune mise en garde à cette règle.
C ++ 11 a introduit le mot-clé
constexpr
qui garantit l'évaluation d'une expression au moment de la compilation et permet au compilateur d'optimiser le code. Maintenant, si la valeur d'une variable statique const dans une étendue est connue au moment de la compilation, le code est optimisé d'une manière similaire à celle avecconstexpr
. Voici un petit exempleJe recommande également aux lecteurs de rechercher la différence entre
constexpr
etstatic const
pour les variables dans ce thread stackoverflow . ceci conclut mon explication du mot-clé statique appliqué aux variables.Mot-clé 'statique' utilisé pour les fonctions
en termes de fonctions, le mot-clé statique a une signification simple. Ici, il se réfère à la liaison de la fonction Normalement, toutes les fonctions déclarées dans un fichier cpp ont un lien externe par défaut, c'est-à-dire qu'une fonction définie dans un fichier peut être utilisée dans un autre fichier cpp par déclaration directe.
l'utilisation d'un mot clé statique avant la déclaration de fonction limite son lien à interne , c'est-à-dire qu'une fonction statique ne peut pas être utilisée dans un fichier en dehors de sa définition.
C. Mot-clé Staitc utilisé pour les variables membres et les fonctions des classes
1. mot clé "statique" pour les variables membres des classes
Je commence directement avec un exemple ici
Dans cet exemple, la variable statique m_designNum conserve sa valeur et cette seule variable membre privée (car elle est statique) est partagée n / b toutes les variables du type d'objet DesignNumber
De même que les autres variables membres, les variables membres statiques d'une classe ne sont associées à aucun objet de classe, ce qui est démontré par l'impression de anyNumber dans la fonction principale
const vs variables de membres statiques non const dans la classe
(i) Variables de membre statique de classe non const Dans l'exemple précédent, les membres statiques (publics et privés) n'étaient pas constants. La norme ISO interdit l'initialisation des membres statiques non const dans la classe. Par conséquent, comme dans l'exemple précédent, ils doivent être initialisés après la définition de classe, avec la mise en garde que le mot clé statique doit être omis
(ii) les variables membres const-stat de la classe ceci est simple et va avec la convention de l'initialisation des autres variables membres const, c'est-à-dire que les variables membres stat const d'une classe peuvent être initialisées au point de déclaration et elles peuvent être initialisées à la fin de la déclaration de classe avec une mise en garde que le mot clé const doit être ajouté au membre statique lors de son initialisation après la définition de classe.
Je recommanderais cependant d'initialiser les variables de membre statique const au point de déclaration. Cela va avec la convention C ++ standard et rend le code plus propre
pour plus d'exemples sur les variables membres statiques dans une classe, recherchez le lien suivant sur learncpp.com http://www.learncpp.com/cpp-tutorial/811-static-member-variables/
2. Mot clé "statique" pour la fonction membre des classes
Tout comme les variables membres des classes peuvent être statiques, les fonctions membres des classes peuvent également l'être. Les fonctions membres normales des classes sont toujours associées à un objet du type classe. En revanche, les fonctions membres statiques d'une classe ne sont associées à aucun objet de la classe, c'est-à-dire qu'elles n'ont pas * ce pointeur.
Deuxièmement, puisque les fonctions membres statiques de la classe n'ont pas * ce pointeur, elles peuvent être appelées à l'aide de l'opérateur de résolution de nom et de portée de classe dans la fonction principale (ClassName :: functionName ();)
Troisièmement, les fonctions membres statiques d'une classe ne peuvent accéder qu'aux variables membres statiques d'une classe, car les variables membres non statiques d'une classe doivent appartenir à un objet de classe.
pour plus d'exemples sur les fonctions membres statiques dans une classe, recherchez le lien suivant sur learncpp.com
http://www.learncpp.com/cpp-tutorial/812-static-member-functions/
la source
struct Foo{static const std::string name = "cpp";};
erreur,name
doivent être définies en dehors de la classe; avec des variables en ligne intruduites en c ++ 17, on peut coder:struct Foo{static inline const std::string name = "cpp";};
2) Les fonctions publiques membres / membres statiques sont accessibles par nom de classe avec l'opérateur de résolution de portée et également une instance avec l'opérateur point (par exemple: instance.some_static_method ())C'est en fait assez simple. Si vous déclarez une variable comme statique dans la portée d'une fonction, sa valeur est préservée entre les appels successifs à cette fonction. Alors:
s'affichera
678
au lieu de666
, car il se souvient de la valeur incrémentée.Quant aux membres statiques, ils conservent leur valeur dans toutes les instances de la classe. Donc le code suivant:
affichera 4, car first.a et second.a sont essentiellement la même variable. Quant à l'initialisation, voir cette question.
la source
Lorsque vous déclarez une
static
variable à la portée du fichier, cette variable n'est disponible que dans que ce fichier particulier (techniquement, l'unité de traduction *, mais ne compliquons pas cela trop). Par exemple:a.cpp
b.cpp
main.cpp:
Pour une variable locale ,
static
signifie que la variable sera initialisée à zéro et conservera sa valeur entre les appels:Pour les variables de classe , cela signifie qu'il n'y a qu'une seule instance de cette variable qui est partagée entre tous les membres de cette classe. Selon les autorisations, la variable est accessible depuis l'extérieur de la classe en utilisant son nom complet.
Marquage d'une fonction non-classe comme
static
rend la fonction uniquement accessible à partir de ce fichier et inaccessible à partir d'autres fichiers.a.cpp
b.cpp
Pour les fonctions membres de la classe, les marquer comme
static
signifie que la fonction n'a pas besoin d'être appelée sur une instance particulière d'un objet (c'est-à-dire qu'elle n'a pas dethis
pointeur).la source
Les variables statiques sont partagées entre chaque instance d'une classe, au lieu que chaque classe ait sa propre variable.
Chaque instance de «MyClass» a son propre «myVar», mais partage le même «myStaticVar». En fait, vous n'avez même pas besoin d'une instance de MyClass pour accéder à 'myStaticVar', et vous pouvez y accéder en dehors de la classe comme ceci:
Lorsqu'il est utilisé dans une fonction en tant que variable locale (et non en tant que variable membre d'une classe), le mot clé statique fait quelque chose de différent. Il vous permet de créer une variable persistante, sans donner de portée globale.
C'est une variable globale en termes de persistance ... mais sans être globale en portée / accessibilité.
Vous pouvez également avoir des fonctions membres statiques. Les fonctions statiques sont essentiellement des fonctions non membres, mais à l'intérieur de l'espace de noms du nom de classe, et avec un accès privé aux membres de la classe.
Lorsque vous appelez une fonction membre, il y a un paramètre caché appelé «this», c'est-à-dire un pointeur vers l'instance de la classe appelant la fonction. Les fonctions membres statiques n'ont pas ce paramètre caché ... elles peuvent être appelées sans instance de classe, mais ne peuvent pas non plus accéder aux variables membres non statiques d'une classe, car elles n'ont pas de pointeur «this» avec lequel travailler. Ils ne sont appelés sur aucune instance de classe spécifique.
la source
myStaticVar
doit également être défini. Un peu important de mentionner que lorsque vous répondez à une question sur la sémantique dustatic
mot - clé, vous ne pensez pas?Je ne suis pas un programmeur C, donc je ne peux pas vous donner correctement des informations sur l'utilisation de statique dans un programme C, mais en ce qui concerne la programmation orientée objet, static déclare fondamentalement qu'une variable, une fonction ou une classe est la même pendant toute la durée du programme. Prends pour exemple.
Lorsque vous instanciez cette classe dans votre Main, vous faites quelque chose comme ça.
Ces deux instances de classe sont complètement différentes l'une de l'autre et fonctionnent indépendamment l'une de l'autre. Mais si vous deviez recréer la classe A comme ça.
Revenons à nouveau au principal.
Alors a1 et a2 partageraient la même copie de int x, de sorte que toute opération sur x dans a1 influencerait directement les opérations de x dans a2. Donc, si je devais faire ça
Les deux instances de la classe A partagent des variables et des fonctions statiques. J'espère que ça répond à ta question. Ma connaissance limitée de C me permet de dire que la définition d'une fonction ou d'une variable comme statique signifie que le fichier est uniquement visible dans lequel la fonction ou la variable est définie comme statique. Mais cela serait mieux répondu par un gars C et pas moi. C ++ permet à la fois C et C ++ de déclarer vos variables comme statiques car il est complètement rétrocompatible avec C.
la source
Oui - Non global, comme une variable locale de fonction.
Droite.
c'est-à-dire que toutes les instances de
R
partageint R::a
-int R::a
ne sont jamais copiées.Effectivement un global qui a constructeur / destructeur le cas échéant - l'initialisation n'est pas différée jusqu'à l'accès.
Pour une fonction locale, elle est externe. Accès: Il est accessible à la fonction (à moins bien sûr que vous ne la renvoyiez).
Pour une classe, c'est externe. Accès: des spécificateurs d'accès standard s'appliquent (public, protégé, privé).
static
peut également spécifier un lien interne, selon l'endroit où il est déclaré (fichier / espace de noms).Il a trop de fonctions en C ++.
Il est automatiquement initialisé avant
main
s'il est chargé et possède un constructeur. Cela peut sembler une bonne chose, mais l'ordre d'initialisation est largement hors de votre contrôle, donc l'initialisation complexe devient très difficile à maintenir, et vous voulez minimiser cela - si vous devez avoir une statique, alors les échelles locales fonctionnent bien mieux dans les bibliothèques et projets. En ce qui concerne les données avec une durée de stockage statique, vous devez essayer de minimiser cette conception, en particulier si elle est modifiable (variables globales). Le «temps» d'initialisation varie également pour un certain nombre de raisons - le chargeur et le noyau ont quelques astuces pour minimiser l'empreinte mémoire et différer l'initialisation, en fonction des données en question.la source
Objet statique: nous pouvons définir des membres de classe statiques à l'aide d'un mot clé statique. Lorsque nous déclarons un membre d'une classe comme statique, cela signifie que peu importe le nombre d'objets de la classe créés, il n'y a qu'une seule copie du membre statique.
Un membre statique est partagé par tous les objets de la classe. Toutes les données statiques sont initialisées à zéro lorsque le premier objet est créé, si aucune autre initialisation n'est présente. Nous ne pouvons pas le mettre dans la définition de classe, mais il peut être initialisé en dehors de la classe comme dans l'exemple suivant en redéclarant la variable statique, en utilisant l'opérateur de résolution de portée :: pour identifier à quelle classe il appartient.
Essayons l'exemple suivant pour comprendre le concept de membres de données statiques:
Lorsque le code ci-dessus est compilé et exécuté, il produit le résultat suivant:
Membres de fonction statiques: en déclarant un membre de fonction statique, vous le rendez indépendant de tout objet particulier de la classe. Une fonction membre statique peut être appelée même si aucun objet de la classe n'existe et que les fonctions statiques sont accessibles en utilisant uniquement le nom de classe et l'opérateur de résolution de portée ::.
Une fonction membre statique ne peut accéder qu'aux membres de données statiques, aux autres fonctions membres statiques et à toute autre fonction extérieure à la classe.
Les fonctions membres statiques ont une portée de classe et n'ont pas accès au pointeur this de la classe. Vous pouvez utiliser une fonction membre statique pour déterminer si certains objets de la classe ont été créés ou non.
Essayons l'exemple suivant pour comprendre le concept de membres de fonction statiques:
Lorsque le code ci-dessus est compilé et exécuté, il produit le résultat suivant:
la source