905 votes

C++ design pattern Singleton

Récemment, je suis tombé sur une réalisation/mise en œuvre du modèle de conception Singleton pour le C++. Il a regardé comme ça (je l'ai adopté à partir de l'exemple réel):

// a lot of methods are omitted here
class Singleton
{
   public:
       static Singleton* getInstance( );
       ~Singleton( );
   private:
       Singleton( );
       static Singleton* instance;
};

À partir de cette déclaration, je peux en déduire que le champ d'instance est lancée sur le tas. Cela signifie qu'il ya une allocation de mémoire. Ce qui est tout à fait clair pour moi, c'est quand exactement la mémoire va être libéré? Ou il y a un bug et une fuite de mémoire? Il semble qu'il y est un problème dans la mise en œuvre.

Ma principale question est, comment puis-je mettre en œuvre dans le droit chemin?

1410voto

Loki Astari Points 116129

Voir cet article pour une conception simple pour un paresseux évalué avec la garantie de la destruction de singleton:
Quelqu'un peut-il me fournir un échantillon de Singleton en c++?

Le classique paresseux évalués correctement et détruit singleton.

class S
{
    public:
        static S& getInstance()
        {
            static S    instance; // Guaranteed to be destroyed.
                                  // Instantiated on first use.
            return instance;
        }
    private:
        S() {};                   // Constructor? (the {} brackets) are needed here.
        // Dont forget to declare these two. You want to make sure they
        // are unaccessable otherwise you may accidently get copies of
        // your singleton appearing.
        S(S const&);              // Don't Implement
        void operator=(S const&); // Don't implement
};

Voir cet article sur quand utiliser un singleton: (pas souvent)
Singleton: Comment doit-il être utilisé

Voir cet article sur l'ordre d'initialisation et d'y faire face:
Statique des variables initialisation de l'ordre
Trouver C++ statique de l'ordre d'initialisation des problèmes

Voir cet article décrivant la durée de vie:
Quelle est la durée de vie d'une variable static dans une fonction C++?

Voir cet article qui traite de certains filetage implications pour les singletons:
Instance du Singleton déclarée comme variable statique de la méthode GetInstance

Voir cet article qui explique pourquoi une double vérification de verrouillage ne fonctionne pas sur C++:
Ce sont toutes les communes de comportements indéfinis qu'un programmeur C++ devrait connaître?

67voto

Cătălin Pitiș Points 10520

Vous pourriez éviter d'allocation de mémoire. Il existe de nombreuses variantes, toutes ayant des problèmes en cas de multithreading environnement.

Je préfère ce genre de mise en œuvre (en fait, il n'est pas correctement dit, je préfère, parce que je éviter les singletons autant que possible):

class Singleton
{
private:
   Singleton();

public:
   static Singleton& instance()
   {
      static Singleton INSTANCE;
      return INSTANCE;
   }
};

Il n'a pas d'allocation dynamique de la mémoire.

55voto

Reed Copsey Points 315315

Être un Singleton, habituellement, vous ne voulez pas qu'elle soit détruite.

Il sera déchirée vers le bas et libéré lorsque le programme se termine, ce qui est normal, le comportement désiré pour un singleton. Si vous voulez être en mesure explicitement le nettoyer, il est assez facile d'ajouter une méthode statique de la classe qui permet de le restaurer à un état de propreté, et de réaffecter la prochaine fois qu'il l'utilise, mais c'est en dehors de la portée d'un "classique" singleton.

16voto

James Hopkin Points 8318

Un autre non-attribution de remplacement: créer un singleton, dire de la classe C, comme vous en avez besoin:

singleton<C>()

à l'aide de

template <class X>
X& singleton()
{
    static X x;
    return x;
}

Ni ceci, ni Cătălin réponse est automatiquement thread-safe dans le courant de C++, mais sera dans C++0x.

7voto

SadSido Points 1569

La solution dans la accepté de répondre a un inconvénient important - le destructeur pour le singleton est appelée après que le contrôle des feuilles de la "main" de la fonction. Il peut y avoir des problèmes vraiment, lorsque certains objets qui en dépendent sont allouées à l'intérieur de "principal".

J'ai rencontré ce problème, lorsque vous essayez d'introduire un Singleton dans l'application Qt. J'ai décidé, que toutes mes boîtes de dialogue configuration doit être Singletons, et a adopté le schéma ci-dessus. Malheureusement, Qt classe principale "QApplication" a été alloué sur la pile dans le "principal" de la fonction, et Qt interdit de créer ou de détruire les boîtes de dialogue lorsque aucun objet application est disponible.

C'est pourquoi je préfère allouées sur la pile des singletons. - Je fournir un explicite "init()" et "le terme()" méthodes pour tous les singletons et de les appeler à l'intérieur de "principal". Ainsi, j'ai le plein contrôle sur l'ordre de singletons création/destruction, et aussi je peux vous garantir que les singletons sera créé, peu importe si quelqu'un l'a appelé "getInstance()" ou pas.

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