webentwicklung-frage-antwort-db.com.de

C ++ Singleton vs. globales statisches Objekt

Ein Freund von mir hat mich heute gefragt, warum er Singleton dem globalen statischen Objekt vorziehen soll. Die Art und Weise, wie ich damit angefangen habe, war, dass der Singleton einen Zustand haben kann und ein statisches globales Objekt nicht ... aber dann war ich mir nicht sicher.

Was sind die Vorteile gegenüber dem anderen? (in C++)

53
Tom

Tatsächlich ist in C++ ein lokales statisches Objekt bevorzugt.

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

Dies ist technisch gesehen ein Singleton. Diese Funktion kann sogar eine statische Methode einer Klasse sein. Daher ist es im Gegensatz zu globalen statischen Objekten, die in beliebiger Reihenfolge erstellt werden können, garantiert, dass sie vor der Verwendung erstellt werden. Dadurch kann ein nicht konsistenter Fehler auftreten, wenn ein globales Objekt ein anderes verwendet. Dies ist ein weit verbreitetes Szenario.

Was es besser macht als die übliche Methode, Singletons mit dem Erstellen einer neuen Instanz durch Aufrufen von new zu erstellen, ist, dass der Objektdestruktor am Ende eines Programms aufgerufen wird. Bei einem dynamisch zugewiesenen Singleton ist dies nicht der Fall.

Eine weitere positive Seite ist, dass es keine Möglichkeit gibt, auf Singleton zuzugreifen, bevor es erstellt wurde, selbst aus anderen statischen Methoden oder aus Unterklassen. Spart Zeit beim Debuggen.

57
vava

In C++ ist die Reihenfolge der Instanziierung statischer Objekte in verschiedenen Kompilierungseinheiten nicht definiert. Auf diese Weise kann ein Global auf ein anderes verweisen, das nicht konstruiert ist, wodurch Ihr Programm in die Luft gejagt wird. Das Singleton-Muster behebt dieses Problem, indem die Konstruktion an eine statische Elementfunktion oder eine freie Funktion gebunden wird.

Es gibt eine anständige Zusammenfassung hier .

24
rlbond

Ein Freund von mir hat mich heute gefragt, warum er Singleton dem globalen statischen Objekt vorziehen soll. Die Art und Weise, wie ich damit anfing, war, dass der Singleton einen Zustand haben kann und ein statisches globales Objekt nicht ... aber dann war ich mir nicht sicher ... weil dies in C++ ... war (ich kam aus C #)

Ein statisches globales Objekt kann auch in C # einen Status haben:

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

Was sind die Vorteile gegenüber dem anderen? (in C++)

Ein Singleton lähmt Ihren Code, eine globale statische Instanz nicht. Es gibt unzählige Fragen zu SO über die Probleme mit Singletons bereits. Hier ist eine , nd eine andere , oder eine andere =.

Kurz gesagt, ein Singleton bietet Ihnen zwei Dinge:

  • ein global zugängliches Objekt und
  • eine Garantie, dass nur eine Instanz erstellt werden kann.

Wenn wir nur den ersten Punkt wollen, sollten wir ein global zugängliches Objekt erstellen. Und warum sollten wir jemals die zweite wollen? Wir wissen nicht im Voraus , wie unser Code in Zukunft verwendet werden kann. Warum sollten wir ihn also festnageln und die möglicherweise nützlichen Funktionen entfernen? Wir liegen normalerweise falsch , wenn wir voraussagen, dass "ich nur eine Instanz benötige". Und es gibt einen großen Unterschied zwischen "Ich brauche nur eine Instanz" (die richtige Antwort ist dann, eine Instanz zu erstellen ) und "Die Anwendung kann unter keinen Umständen korrekt ausgeführt werden Wenn mehr als eine Instanz erstellt wird, stürzt sie ab, formatiert die Festplatte des Benutzers und veröffentlicht vertrauliche Daten im Internet. "(Die Antwort lautet dann: Höchstwahrscheinlich ist Ihre App defekt, aber wenn Es ist also nicht so, ein Singleton ist das, was du brauchst.

8
jalf

Ein weiterer Vorteil des Singleton gegenüber dem globalen statischen Objekt ist, dass es eine sehr klare, vom Compiler erzwungene Anweisung gibt, die besagt, dass es nur eine geben kann, da der Konstruktor privat ist.

Im Vergleich zum globalen statischen Objekt steht einem Entwickler, der Code schreibt, der eine zusätzliche Instanz dieses Objekts erstellt, nichts mehr im Wege.

Der Vorteil der zusätzlichen Einschränkung besteht darin, dass Sie eine Garantie dafür haben, wie das Objekt verwendet wird.

4
Andrew Shepherd

Grund 1:
Singletons sind einfach herzustellen und daher faul zu bauen.
Während Sie dies mit Globals tun können, benötigt der Entwickler zusätzliche Arbeit. Daher werden Globals standardmäßig immer initialisiert (abgesehen von einigen Sonderregeln mit Namespaces).

Wenn Ihr Objekt also groß und/oder teuer in der Herstellung ist, möchten Sie es möglicherweise nicht bauen, es sei denn, Sie müssen es wirklich verwenden.

Grund 2:
Problem mit der Reihenfolge der Initialisierung (und Zerstörung).

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

Mit dem Singleton-Idiom ("construct on first use") können Sie statisches Fiasko der Initialisierungsreihenfolge vermeiden

3
aJ.

In C++ gibt es keinen großen Unterschied zwischen den beiden in Bezug auf die tatsächliche Nützlichkeit. Ein globales Objekt kann natürlich seinen eigenen Zustand beibehalten (möglicherweise mit anderen globalen Variablen, obwohl ich es nicht empfehle). Wenn Sie ein globales oder ein Singleton verwenden (und es gibt viele Gründe, dies nicht zu tun), liegt der Hauptgrund für die Verwendung eines Singleton über einem globalen Objekt darin, dass Sie mit einem Singleton einen dynamischen Polymorphismus erzielen können, indem Sie mehrere Klassen erben lassen eine Singleton-Basisklasse.

0
coppro