8
votes

C ++ MEMBRE STATIQUE Portée variable

Le titre dit essentiellement tout cela, je me demande lorsque des membres statiques d'une classe C ++ sont initialisés et quand ils sont hors de portée.

J'ai besoin de cela pour le problème suivant. J'ai de nombreux objets d'une classe FOO et chaque objet a besoin d'accès à une ressource, encapsulé par une autre barre de classe. La synchronisation n'est pas un problème, je souhaite donc que tous les objets partagent la même instance de barre. P>

J'utilise un simple pointeur géré pour le comptage de référence. P>

Puis-je faire ce qui suit: P>

class Foo {
private:
    static managed_pointer<Bar> staticBar;
public:
    Foo() {
        if(!staticBar)
            staticBar = new Bar;
    }
    /*
     * use staticBar in various non-static member functions
     */
};

managed_pointer<Bar> Foo::staticBar = NULL;


2 commentaires

Oups, merci de réparer la faute de frappe.


La dernière instance de FOO est détruite lorsque vous supprimez simplement la dernière instance ou lorsque votre programme existe. Un membre statique d'une classe existera, peu importe le nombre d'instances de la classe.


3 Réponses :


13
votes

statique s et globaux sont initialisés juste avant que le programme ne commence (avant principal est appelé, le programme commence réellement avant cela) et sortez de la portée après principale sort.

Exceptions - Statique locale (Variables statiques déclarées des fonctions internes) et Classe de modèle inutilisée Statique Membres.

Cela n'a rien à voir avec le nombre d'instances.


11 commentaires

Les variables statiques locales ne sont pas initialisées avant le début du programme.


OK merci. Qu'entendez-vous par «cela n'a rien à voir avec le nombre d'instances»? Instances de la classe foo?


Oui, peu importe le nombre d'instances de FOO, ils partagent tous la barre.


@Gabi ni des membres statiques non utilisés si la classe est un modèle.


@ Lesnip3r: Oui bien sûr, c'est l'intention, sinon je ne pouvais que faire bar un membre non statique et laisser foo s cors et dtor prennent soin de l'allocation / la suppression < Code> bar .


statique et les globaux sont initialisés juste avant que le programme ne commence est trompeur. Le programme commence avant l'initialisation est effectué (le programme démarre bien avant principal ), et , il est indéterminé si les variables avec durée statique sont initialisées Avant la première instruction dans principale est exécutée. La garantie est que l'initialisation doit être effectuée avant la première odr-use de la statique.


Les variables statiques de la classe sont hors de portée en dehors de la définition de la classe (ou de ses classes dérivées) et des définitions de membres de la classe (et des définitions des membres de la classe dérivée). Ce n'est pas la même chose que lorsque leur vie se termine.


@ Davidrodríguez-Dribesas C'est ce que je voulais dire. Mais je ne connais aucune implémentation qui initie la statique après avoir entré la principale mais avant utilisation.


Que se passe-t-il si le code n'est pas pour un programme avec une fonction Main () mais pour une bibliothèque dynamique?


@Daniel est la bibliothèque dynamique chargée lorsque le programme démarre ou de manière dynamique (LoadLibrary)?


Je ne savais pas que cela fait une différence. Personnellement, je demande à propos d'un module C ++ pour Python - donc je suppose que c'est le second cas: la bibliothèque n'est pas chargée immédiatement lorsque l'interpréteur Python commence mais lorsque le module est importé dans le code Python. Cependant, si quelqu'un avait une réponse universelle, ce serait tout meilleur.



2
votes

La norme ne spécifie pas d'ordre d'initialisation précis, il est spécifique de la mise en œuvre. Ils seront instanciés au début du programme et seront traités à la fin.

Vous devez faire très attention à ce que vous faites, car si vous avez d'autres objets statiques qui comptent sur cet objet, c'est UB. Il n'y a pas de dire dans quel ordre ils seront initialisés.

Vous pouvez éventuellement regarder quelque chose comme Boost :: Call_Oronce Pour que ce soit initialisé une fois, mais je ne voudrais pas compter sur la commande que les statiques sont initialisées.

Pour tout ce que je sais, votre code fonctionnerait, mais j'ai été mordu par la question d'initialisation statique avant de pouvoir vous avertir.

Edit: également dans votre code, lorsque le géré_ptr sera hors de portée (fin du programme), il supprimera la mémoire allouée automatiquement. Mais vous ne devriez pas faire quelque chose de non-trivial dans le destructeur de la barre, car vous pouvez déclencher UB en appelant d'autres instances libres ou même du code qui a été supprimé (car cela m'est arrivé une fois qu'une bibliothèque dynamique avait été supprimée). Essentiellement, vous êtes dans un champ de mines, alors faites attention.


2 commentaires

Je n'aurai pas d'autre statique S à FOO, mais merci pour l'avertissement, un autre détail bien d'avoir à l'esprit. Edit: Merci également pour le deuxième avertissement, je vais regarder.


Je voulais dire, d'autres objets statiques dans votre programme . Si plus tard, vous décidez d'avoir un autre objet, disons une barre d'armature, c'est aussi statique, et vous pensez que «hey je peux appeler bar :: quelque chose puisqu'il est statique» Vous devez faire attention.



1
votes

La première chose qui sort de votre question est la fausse idée commune que portée et vie sont des concepts équivalents. Ils ne sont pas. Dans certains cas, comme avec les variables locales, la Lifetime est liée à un contexte particulier , mais ce n'est pas toujours le cas.

une variable de membre statique de classe a la portée de la classe (il est accessible n'importe où dans le programme) et la durée de vie statique , ce qui signifie qu'il va être initialisé dans l'ordre par rapport aux autres variables statiques dans la même unité de traduction et dans une commande non définie en ce qui concerne d'autres variables statiques dans d'autres unités de traduction, avant principale (mise en garde: l'initialisation n'a pas besoin d'être effectuée Avant la première déclaration de la principale, mais il est garanti d'être avant la première user d'ODR de la variable).


1 commentaires

Une variable de membre statique de classe a classe Scope: il n'est visible que dans les contextes où les noms sont recherchés dans la classe. Il a une vie statique et une liaison externe (un troisième concept que les gens confondent parfois avec les deux que vous mentionnez). Pourtant, vous avez mentionné le point essentiel: la durée de vie et la portée sont des concepts orthogonaux. (Au moins dans un degré. Il sont des cas lorsque la portée détermine la durée de vie.)