12
votes

Est-ce juste une bonne façon de créer une classe singleton par faible_ptr

Je crée une classe parent pour gérer le motif singleton avec un pointeur intelligent:

.h Fichier: p>

template<class singleType>
std::shared_ptr<singleType> Singleton<singleType>::GetInstance()
{
    auto shareObject = m_singleObject.Lock();
    if (!shareObject)
    {
        shareObject.reset(new singleType);
        m_singleObject = shareObject;
    }

    return shareObject;
}


5 commentaires

Ainsi, l'idée de base qu'une fois que tous les pointeurs du singleton sont hors de portée, le singleton est supprimé. Ensuite, plus tard, lorsque vous avez besoin d'un pointeur sur le singleton, vous créez une nouvelle singleton? Si tel est le cas, il a l'air bien. Je n'ai pas essayé, mais tout a l'air bien.


... Mon imagination sur les singletons est qu'ils ne devraient pas supprimer pendant que le programme est vivant. N'est-ce pas?


@Mm. Assez souvent, oui. Parfois, c'est aussi "il ne peut y avoir aucun ou un, mais jamais plus."


Le moyen "droit" de créer un singleton? Qui vous a dit qu'une telle chose est possible? La bonne chose est de ne pas créer de singleton.


@jalf: afflux soudain de questions singleton. :(


4 Réponses :


1
votes

Au meilleur de ma connaissance, cela devrait aller bien. Vous éviterez des problèmes de destruction hors commandes, mais cela pourrait être un problème de créer de nouvelles instances après la création de votre instance initiale. Ce singleton n'aura qu'une seule instance vivante à tout moment, mais au cours du programme exécutant plus d'une instance peut avoir été vivant dans l'ensemble.

Cette destruction et cette récréation peuvent également être indésirables en termes de performance, non seulement dans les effets secondaires.


0 commentaires

4
votes

J'ai fait des recherches alors maintenant je posterai une réponse.

Le code semble tout ce qui devrait fonctionner et est une utilisation correcte des pointeurs intelligents. La seule question est de savoir comment exactement vous voulez que le singleton se comporte. Cela devrait se comporter comme un manuel singleton à l'exception du comportement que si rien n'a actuellement un pointeur sur le singleton, il se supprimera. Ce comportement est quelque chose qui dépend vraiment de la mise en œuvre de votre programme. Si vous voulez que le Singelton n'existe que lorsqu'il est utilisé, alors je dirais que je vais y aller.

Je voudrais simplement éviter de créer et de détruire le Singelton trop souvent surtout si la construction et la déconstruction sont particulièrement intensives. S'il est constamment créé et supprimé, vous êtes probablement meilleur avec une implémentation Singleton plus standard. Le comportement standard singleton a tendance à être qu'un singleton n'est créé qu'une fois pendant la durée du programme en cours d'exécution et n'est jamais supprimé.

Je pense que c'est une implémentation intelligente étant donné que vous avez une utilisation pour cela et je pourrais avoir à emprunter l'idée.


4 commentaires

C'est une idée étrange de supprimer puis de recréer (si nécessaire) un seul objet! Ce n'est pas intelligent d'avoir Singleton en premier lieu, mais vous essayez de le rendre encore pire.


Je ne veux pas discuter des mérites des singletons, mais je pouvais voir cette méthode utile surtout si le singleton n'est pas utilisé souvent et que le singleton a une empreinte de mémoire particulièrement importante. Dans beaucoup de cas, ils sont une mauvaise idée, mais dans d'autres, ils sont très utiles et seraient difficiles à écrire du code sans.


C'est un problème de tester le code avec Singleton, mais cette implémentation particulière rend presque impossible.


Je prétends toujours que cela dépend exactement de la façon dont ils sont utilisés, mais je pense que nous devrons accepter de ne pas être d'accord.



4
votes

Votre code n'est pas le fil sûr.

Le nom verrouillage peut suggérer que l'accès simultané est bloqué, mais il n'y a pas de telle garantie: lorsque plusieurs threads appellent simultanément votre fonction geInstance Vous obtiendrez plusieurs instances au lieu de garantir une seule.

Vous devez créer une serrure explicite pendant toute la durée de la durée de vie du geInstance . Notez que cela n'est bien sûr pas très efficace.


0 commentaires

3
votes

Les avantages et les inconvénients de cette mise en œuvre sont déjà discutés. Mais il y a un tas de bugs:

1) car il s'agit d'un modèle que vous devez déplacer votre implémentation dans l'en-tête ou que la liaison ne peut pas le trouver.

2) Le .Olock ( ) La fonction de la faiblesse_ptr n'est pas dans les capitales.

3) N'oubliez pas d'instancier xxx

4) meilleure utilisation ShareObject = std :: make_shared (singletype (singletype ()); au lieu du nouveau : http://herbstert.com/gotw/_103/

5) Comme Konrad mentionné: ce n'est pas le fil-coffre-fort.


3 commentaires

Merci Gerrit, seulement à propos du point 2, STD :: Faible_ptr fonction est .Lock (). Boost est .lock ().


@MarkGuo je n'ai essayé que par Clang et Libc ++. Il y a son .lock (). Et voyez ici: EN.CPPREFERFERFER.COM/W/CPP/MEMORY/WEAK_PTRIDE >


Utiliser make_shared ne fonctionnerait pas si vous faites votre constructeur privé. (ce que je pense que vous devriez devoir pour un singleton)