2012-07-20 4 views
2

je mets en œuvre habituellement le singleton C++ ainsi:différentes implémentations singleton

class Singleton 
{ 
    public: 
     virtual ~Singleton() {} 

     static Singleton& GetInstance() 
     { 
      static Singleton instance; 
      return instance; 
     } 

    private: 
     Singleton(); 
     Singleton(const Singleton&); 
     Singleton& operator=(const Singleton&); 
} 

Récemment, je suis tombé sur cette mise en œuvre, ce qui est légèrement différente:

class Singleton 
{ 
    public: 
     Singleton(); 
     virtual ~Singleton() {} 

     static Singleton& GetInstance() 
     { 
      return instance; 
     } 

    private: 
     Singleton(const Singleton&); 
     Singleton& operator=(const Singleton&); 

     static Singleton instance; 
} 

Singleton Singleton::instance; 

Quelle mise en œuvre est mieux?

N'est-il pas dangereux de ne pas rendre le constructeur privé (2ème implémentation)?

Merci.

Répondre

3

Il existe une différence. Dans le premier cas instance est initialisé lors du premier appel de la fonction. Dans le second cas, il est initialisé au démarrage du programme.

Si vous faites un constructeur public - Ce n'est pas singleton, car il est peut être créé par une personne

1

La deuxième application est mal. Le constructeur par défaut doit être privé. Tel qu'il est, ce n'est pas un singleton en soi. En outre, les différences entre les implémentations sont mentionnées dans les réponses @Andrew et @Brady.

0

Une différence importante entre les deux est que la création de l'instance dans le second exemple est thread-safe.

Vous avez absolument raison, le constructeur devrait être privé.

est ici une question connexe: https://stackoverflow.com/a/10479084/1158895

3

La principale différence de comportement viendra si vous essayez d'utiliser le singleton lors de l'initialisation d'une autre variable de niveau d'espace de noms ou un membre statique de classe. Dans le premier cas, puisque l'objet réel est créé à la demande lors du premier appel de fonction, le comportement lors de la contruction sera bien défini. Dans le second cas, tous les paris sont désactivés, car l'ordre relatif d'initialisation des objets statiques provenant d'unités de traduction différentes n'est pas défini. Notez également que si le premier est sûr pendant construction, il peut ne pas être pendant la destruction. C'est-à-dire, si un objet avec une durée de stockage statique n'utilise pas le singleton pendant la construction, il peut être initialisé avant l'instance de singleton. L'ordre de destruction est inversé par rapport à l'ordre de construction, et dans ce cas particulier le singleton serait détruit avant l'autre objet. Si cet objet utilise le singleton dans son destructeur, il provoquera un comportement indéfini.

4

Je n'ai pas besoin de répéter le bon point sur la construction paresseuse du singleton faite dans d'autres réponses.

Permettez-moi d'ajouter ceci:

public: 
    Singleton(); 
    virtual ~Singleton() {} 

Le designer de cette classe particulière a ressenti le besoin de permettre:

  • dérivation de cette classe Singleton, disons que la classe dérivée est appelée DerSingleton
  • DerSingleton peut avoir des instances qui peuvent être supprimées avec un pointeur vers Singleton (si DerSingleton n'est pas un singleton)

Toute instance de DerSingleton est également une instance Singleton par définition, il en résulte que si DerSingleton est instancié, Singleton n'est pas un singleton.

donc cette conception deux choses: affirme

  • cette classe est un singleton
  • cette classe est pas un singleton
Questions connexes