Comment est-Meyers mise en œuvre d'un Singleton en fait un Singleton
J'ai lu beaucoup de choses sur les Singletons, alors qu'ils devraient et ne devraient pas être utilisés, et comment les mettre en œuvre en toute sécurité. Je suis en train d'écrire en C++11, et en sont venus à travers l'Meyer paresseux initialisé à la mise en œuvre d'un singleton, comme on le voit dans cette question.
Cette mise en œuvre est:
static Singleton& instance()
{
static Singleton s;
return s;
}
Je comprends comment c'est thread-safe à partir d'autres questions ici sur le cas, mais ce que je ne comprends pas, c'est comment ce est en fait un pattern singleton. J'ai mis en œuvre des singletons dans d'autres langues, et ces finissent toujours par quelque chose comme cet exemple de Wikipédia:
public class SingletonDemo {
private static volatile SingletonDemo instance = null;
private SingletonDemo() { }
public static SingletonDemo getInstance() {
if (instance == null) {
synchronized (SingletonDemo .class){
if (instance == null) {
instance = new SingletonDemo ();
}
}
}
return instance;
}
}
Quand je regarde ce deuxième exemple, il est très intuitif comment c'est un singleton, depuis la classe contient une référence à une instance de lui-même, et ce n'est que renvoie cette instance. Cependant, dans le premier exemple, je ne comprends pas comment cela empêche-t-il jamais deux instances de l'objet. Donc mes questions sont:
- Comment la mise en œuvre d'abord appliquer un pattern singleton? Je suppose qu'il a à faire avec le mot-clé static, mais je suis en espérant que quelqu'un peut m'expliquer en profondeur ce qui se passe sous le capot.
- Entre ces deux styles de mise en œuvre, est l'un prime sur l'autre? Quels sont les avantages et les inconvénients?
Merci pour toute aide,
- Le code C++, la façon de le représenter, n'est pas tellement un singleton comme il est bien initialisé objet global. Il n'y a rien qui vous empêche d'avoir un autre de ces (faire une autre fonction), et c'est très bien. Il n'y a pas de forcer quelqu'un à faire quelque chose. Si vous voulez juste un, juste ne font qu'un.
static Singleton s;
, la première fois, la fonction est appelée, cette variable sera initialisée et contrairement à la non-variables statiques elle ne sera pas détruite une fois que la fonction se termine. Ainsi, lorsque vous appelez à nouveau, il continuera d'exister, de sorte que la seule instruction qui sera exécutée le 2ème (3ème, 4ème, ...) le temps est de retour.s.- J'imagine
Singleton
s'constructeur est privé, donc la seule façon de réellement obtenir une instance est viainstance()
fonction. - Les Singletons: il suffit de dire aucun (de plus, votre premier exemple n'est pas un singleton en lui-même. Vous avez laissé un peu de code.)
- Je n'ai absolument aucune idée de pourquoi ce serait classée, principalement par opinion". Ok, la deuxième question peut sembler comme elle, mais il peut très bien être (et sont en réalité) objectif les raisons de préférer une mise en œuvre sur les autres et la première question, tout en manquant de compréhension de la
static
mot-clé, est une question tout à fait pertinente, trop. Ce n'est pas seulement le singleton-haters cris de sang. Sérieusement, je suis un de ceux, trop, mais ni cela fait-il de cette question non valide. +1
Vous devez vous connecter pour publier un commentaire.
C'est un singleton car
static
durée de stockage pour une fonction locale signifie qu'une seule instance de ce local existe dans le programme.Sous le capot, cela peut très grossièrement être considéré comme équivalent à celui-ci C++98 (et pourrait être mis en œuvre vaguement comme cela par un compilateur):
Le fil de sécurité bits de faire obtenir un peu plus compliqué, mais c'est essentiellement la même chose.
À la recherche à une mise en œuvre effective de C++11, il y a un garde variable pour chaque statique (comme le booléen ci-dessus), qui est également utilisé pour les obstacles et les fils. Regardez Clang est AMD64 sortie pour:
AMD64 assemblée pour
instance
de Ubuntu Clang 3.0 sur AMD64 au -O1 (avec l'aimable autorisation de http://gcc.godbolt.org/ est:Vous pouvez voir qu'il fait référence à un mondial de la garde pour voir si l'initialisation est nécessaire, utilise
__cxa_guard_acquire
, tests l'initialisation de nouveau, et ainsi de suite. Exactement dans presque tous les sens comme la version que vous avez posté à partir de Wikipedia, à l'exception de l'aide AMD64 assemblée et les symboles/mise en page spécifiée dans le Itanium ABI.Notez que si vous exécutez ce test, vous devez donner
Singleton
un non-trivial constructeur il n'est donc pas un POD, sinon l'optimiseur va réaliser qu'il n'y a pas de point de faire tout ce qui est de la garde/verrouillage de travail.Cette mise en œuvre est connue comme Meyers Singleton. Scott Meyers dit:
Lorsque vous appelez
Singleton& s=Singleton::Instance()
la première fois que l'objet est créé et chaque appel suivant à
Singleton::Instance()
résultats avec le même objet retourné.Principal problème:
Une autre mise en œuvre s'appelle le fidèle, qui fuit Singleton.
Deux questions:
static Singleton& Instance() { static Singleton *I = new Singleton(); return *I; }
.Singleton s=Singleton::Instance()
, n'est-ce pas vous en fait la création d'une nouvelle instance par défaut (non privé) constructeur de copie? ( Je l'aurais imaginé,Singleton & s=Singleton::Instance()
à la place)