web-dev-qa-db-fra.com

C ++ singleton vs objet statique global

Un de mes amis m'a demandé aujourd'hui pourquoi devrait-il préférer l'utilisation de singleton à un objet statique global? La façon dont je l'ai commencé à expliquer était que le singleton peut avoir un état par rapport à un objet global statique ne le sera pas ... mais alors je n'étais pas sûr ... car cela en C++ .. (je venais de C #)

Quels sont les avantages les uns par rapport aux autres? (en C++)

53
Tom

En fait, de manière préférée en C++ est un objet statique local.

Printer & thePrinter() {
    static Printer printer;
    return printer;
}

C'est techniquement un singleton cependant, cette fonction peut même être une méthode statique d'une classe. Ainsi, il garantit d'être construit avant d'être utilisé contrairement aux objets statiques globaux, qui peuvent être créés dans n'importe quel ordre, ce qui permet d'échouer de manière incohérente lorsqu'un objet global en utilise un autre, un scénario assez courant.

Ce qui le rend meilleur que la façon courante de faire des singletons avec la création d'une nouvelle instance en appelant new, c'est que le destructeur d'objets sera appelé à la fin d'un programme. Cela n'arrivera pas avec un singleton alloué dynamiquement.

Un autre aspect positif est qu'il n'y a aucun moyen d'accéder au singleton avant qu'il ne soit créé, même à partir d'autres méthodes statiques ou de sous-classes. Vous fait gagner du temps de débogage.

57
vava

En C++, l'ordre d'instanciation des objets statiques dans différentes unités de compilation n'est pas défini. Ainsi, il est possible pour un global de référencer un autre qui n'est pas construit, faisant exploser votre programme. Le modèle singleton supprime ce problème en liant la construction à une fonction membre statique ou une fonction libre.

Il y a un bon résumé ici .

24
rlbond

Un de mes amis m'a demandé aujourd'hui pourquoi devrait-il préférer l'utilisation de singleton à un objet statique global? La façon dont je l'ai commencé à expliquer était que le singleton peut avoir un état par rapport à un objet global statique ne le sera pas ... mais alors je n'étais pas sûr ... car cela en C++ .. (Je venais de C #)

Un objet global statique peut également avoir un état en C #:

class myclass {
 // can have state
 // ...
 public static myclass m = new myclass(); // globally accessible static instance, which can have state
}

Quels sont les avantages les uns par rapport aux autres? (en C++)

Un singleton paralyse votre code, pas une instance statique globale. Il y a d'innombrables questions sur SO sur les problèmes avec les singletons déjà. En voici une , et une autre , ou une autre =.

En bref, un singleton vous donne deux choses:

  • un objet accessible à l'échelle mondiale, et
  • une garantie qu'une seule instance peut être créée.

Si nous voulons juste le premier point, nous devons créer un objet accessible globalement. Et pourquoi voudrions-nous jamais le second? Nous ne savons pas à l'avance comment notre code peut être utilisé à l'avenir, alors pourquoi le clouer et supprimer ce qui pourrait être une fonctionnalité utile? Nous avons généralement tort lorsque nous prédisons que "je n'aurai besoin que d'une seule instance". Et il y a une grande différence entre "je n'aurai besoin que d'une seule instance" (la bonne réponse est alors de créer une instance), et "l'application peut ' t en aucun cas fonctionner correctement si plus d'une instance est créée. Elle plantera, formatera le disque dur de l'utilisateur et publiera des données sensibles sur Internet "(la réponse ici est alors: Votre application est probablement cassée, mais si ce n'est pas le cas, alors oui, un singleton est ce dont vous avez besoin)

8
jalf

Un autre avantage du Singleton sur l'objet statique global est que, parce que le constructeur est privé, il existe une directive très claire, appliquée par le compilateur, disant "Il ne peut y en avoir qu'un".

En comparaison, avec l'objet statique global, rien n'arrêtera un développeur qui écrit du code qui crée une instance supplémentaire de cet objet.

L'avantage de la contrainte supplémentaire est que vous avez une garantie sur la façon dont l'objet sera utilisé.

4
Andrew Shepherd

Raison 1:
Les singletons sont faciles à faire, donc ils sont paresseux.
Bien que vous puissiez le faire avec des globaux, cela demande un travail supplémentaire au développeur. Ainsi, par défaut, les globaux sont toujours initialisés (à l'exception de certaines règles spéciales avec des espaces de noms).

Donc, si votre objet est grand et/ou coûteux à construire, vous ne voudrez peut-être pas le construire à moins que vous ne deviez vraiment l'utiliser.

Raison 2:
Problème d'ordre d'initialisation (et de destruction).

GlobalRes& getGlobalRes()
{
    static GlobalRes instance;  // Lazily initialized.
    return instance;
}


GlobalResTwo& getGlobalResTwo()
{
    static GlobalResTwo instance;  // Lazy again.
    return instance;
}


// Order of destruction problem.
// The destructor of this object uses another global object so
// the order of destruction is important.
class GlobalResTwo
{
    public:
        GlobalResTwo()
        {
            getGlobalRes();
            // At this point globalRes is fully initialized.
            // Because it is fully initialized before this object it will be destroyed
            // after this object is destroyed (Guaranteed)
        }
        ~GlobalResTwo()
        {
            // It is safe to use globalRes because we know it will not be destroyed
            // before this object.
            getGlobalRes().doStuff();
        }
};
3
Martin York

En utilisant l'idiome Singleton ("construction lors de la première utilisation"), vous pouvez éviter fiasco d'ordre d'initialisation statique

3
aJ.

En C++, il n'y a pas une énorme différence entre les deux en termes d'utilité réelle. Un objet global peut bien sûr conserver son propre état (éventuellement avec d'autres variables globales, bien que je ne le recommande pas). Si vous allez utiliser un global ou un singleton (et il y a de nombreuses raisons de ne pas le faire), la principale raison d'utiliser un singleton sur un objet global est qu'avec un singleton, vous pouvez avoir un polymorphisme dynamique en ayant plusieurs classes héritant de une classe de base singleton.

0
coppro