mikrocontroller.net

Forum: PC-Programmierung static Variable in C++


Autor: friedelbär (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich habe letztens dieses Konstrukt in C++ gesehen und mich gefragt was 
das eigentlich genau bewirkt:
const Date& default_date()
{
   static const Date dd(1970,1,1); // initialize dd first time we get here
   return dd;
}

Der Vorteil soll sein, dass die Variable "dd" nicht bei jedem Aufruf von 
neuem erstellt wird, was der Fall wäre wenn man das Schlüsselwort 
"static" weglassen würde, was dann speicherintensiver wäre wenn es 
zigtausendmal aufgerufen werden würde.

Bleibt eine Variable die mit "static" deklariert wird auch nach dem 
Verlassen der Funktion bestehen?

Autor: Dr. Sommer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
friedelbär schrieb:
> Bleibt eine Variable die mit "static" deklariert wird auch nach dem
> Verlassen der Funktion bestehen?

Ja, die wird einmal beim Betreten der Funktion angelegt und gilt dann 
für immer. Wenn die nicht "const" ist kann das z.B. beim Multithreading 
problematisch werden. Zudem muss bei jedem Betreten der Funktion geprüft 
werden, ob die Variable bereits initialisiert wurde, was minimal 
ineffizienter ist, als die Variable als statische Klassen-Variable oder 
globale statische Variable anzulegen.

Autor: Rolf M. (rmagnus)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
friedelbär schrieb:
> Der Vorteil soll sein, dass die Variable "dd" nicht bei jedem Aufruf von
> neuem erstellt wird, was der Fall wäre wenn man das Schlüsselwort
> "static" weglassen würde, was dann speicherintensiver wäre wenn es
> zigtausendmal aufgerufen werden würde.

Speicherintensiver nicht. Die Variable existiert ja dann jedes mal nur 
solange, bis die Funktion beendet wird. Aber die Variable muss für jeden 
Aufruf der Funktion eben neu erstellt und nachher wieder zerstört 
werden. Wenn sie static ist, muss das nur einmal gemacht werden.

friedelbär schrieb:
> Bleibt eine Variable die mit "static" deklariert wird auch nach dem
> Verlassen der Funktion bestehen?

Ja. Genau das ist es, was static in einer Funktion bewirkt.

Autor: Friedelbär (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Rolf M. schrieb:
>> Bleibt eine Variable die mit "static" deklariert wird auch nach dem
>> Verlassen der Funktion bestehen?
>
> Ja. Genau das ist es, was static in einer Funktion bewirkt.

Super vielen Dank euch!

Autor: Wilhelm M. (wimalopaan)
Datum:

Bewertung
-1 lesenswert
nicht lesenswert
friedelbär schrieb:
> Hallo,
>
> ich habe letztens dieses Konstrukt in C++ gesehen und mich gefragt was
> das eigentlich genau bewirkt:
>
>
> const Date& default_date()
> {
>    static const Date dd(1970,1,1); // initialize dd first time we get 
> here
>    return dd;
> }
> 

Das hat jetzt gar nichts mit Deinem Thema zu tun, aber man könnte 
überlegen, ob die Klasse bzw. der ctor gut realisiert ist:
Date dd(1970,2,3); 

Welches Datum ist das?

Ein Klasse Date ist geradezu der Klassiker für solche Probleme ...

Autor: Markus L. (rollerblade)
Datum:

Bewertung
-3 lesenswert
nicht lesenswert
Rolf M. schrieb:
> Speicherintensiver nicht.
Doch. Static Locals belegen permanent Speicher, Non-Static nur dann, 
wenn sie im Scope sind.

Autor: mh (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Markus L. schrieb:
> Rolf M. schrieb:
>> Speicherintensiver nicht.
> Doch. Static Locals belegen permanent Speicher, Non-Static nur dann,
> wenn sie im Scope sind.

Und non-static locals können beliebig oft im Speicher liegen bei 
rekursivem Funktionsaufruf.

Autor: Rolf M. (rmagnus)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Markus L. schrieb:
> Rolf M. schrieb:
>> Speicherintensiver nicht.
> Doch. Static Locals belegen permanent Speicher, Non-Static nur dann,
> wenn sie im Scope sind.

Und warum macht das nicht-statische lokale Variablen speicherintensiver?

mh schrieb:
> Und non-static locals können beliebig oft im Speicher liegen bei
> rekursivem Funktionsaufruf.

Ja, oder bei Multithreading, aber es ging hier eigentlich nur um den 
ganz einfachen Fall, ...

friedelbär schrieb:
> wenn es zigtausendmal aufgerufen werden würde.

Autor: Nase (Gast)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Das ist ein Idiom: "magic static", seit C++11 sogar thread-safe.

Autor: Frank M. (ukw) (Moderator) Benutzerseite
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Dr. Sommer schrieb:
> Ja, die wird einmal beim Betreten der Funktion angelegt [...]

Die wird bereits beim Start des Programms angelegt, nicht erst, wenn die 
Funktion "betreten" wird. ;-)

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Frank M. schrieb:
>> Ja, die wird einmal beim Betreten der Funktion angelegt [...]
>
> Die wird bereits beim Start des Programms angelegt, nicht erst, wenn die
> Funktion "betreten" wird. ;-)

Was auch bedeutet, dass der Konstruktur aufgerufen wird, bevor main() 
aktiv ist. Das sollte beachtet werden, wenn in main() irgendwelche 
Initialisierungen erfolgen, von denen der Konstruktor abhängig ist.

Autor: Rolf M. (rmagnus)
Datum:

Bewertung
2 lesenswert
nicht lesenswert
A. K. schrieb:
> Frank M. schrieb:
>>> Ja, die wird einmal beim Betreten der Funktion angelegt [...]
>>
>> Die wird bereits beim Start des Programms angelegt, nicht erst, wenn die
>> Funktion "betreten" wird. ;-)

Nein.

> Was auch bedeutet, dass der Konstruktur aufgerufen wird, bevor main()
> aktiv ist.

Nein.

Das Objekt wird beim ersten Aufruf der Funktion erzeugt. Wird die 
Funktion nie aufgerufen, dann gibt es auch das Objekt nicht.

Autor: db8fs (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
A. K. schrieb:
> Was auch bedeutet, dass der Konstruktur aufgerufen wird, bevor main()
> aktiv ist. Das sollte beachtet werden, wenn in main() irgendwelche
> Initialisierungen erfolgen, von denen der Konstruktor abhängig ist.

Hmm, genau, da kann man in schlimme Probleme durch 
Konstruktionsabhängigkeiten kommen sonst. z.B. die übliche 
Singleton<>-Implementierung, wo 'ne static-Variable in 'ner Funktion 
drinne ist. Schlimm wirds dann, wenn ein Singleton auf ein anderes 
zugreift...

Bin daher auch kein großer Fan von lokalen static-Variablen. Zum Einen 
wegen der Threadsafety-Geschichte, zum Anderen weil es irgendwo 
kontraintuitiv zum OOP-Ansatz ist, 'ne Funktion mit 'nem 
Gedächtnis/Zustand auszustatten - ist 'n irgendwie ein CodeSmell. Würde 
Zustände lieber durch Member von Objekte erreichen, nicht durch solche 
Tricks mit alten C-Sprach-Anleihen.

Just my 2 cents

Autor: Rolf M. (rmagnus)
Datum:

Bewertung
2 lesenswert
nicht lesenswert
db8fs schrieb:
> Würde Zustände lieber durch Member von Objekte erreichen, nicht durch
> solche Tricks mit alten C-Sprach-Anleihen.

Im Gegensatz zu lokalen static-Variblen hat man bei static-Members 
tatsächlich die von die oben geschilderten Probleme.

Autor: db8fs (Gast)
Datum:

Bewertung
-1 lesenswert
nicht lesenswert
Rolf M. schrieb:
> db8fs schrieb:
>> Würde Zustände lieber durch Member von Objekte erreichen, nicht durch
>> solche Tricks mit alten C-Sprach-Anleihen.
>
> Im Gegensatz zu lokalen static-Variblen hat man bei static-Members
> tatsächlich die von die oben geschilderten Probleme.

Nee, nee, die kann man so auch kriegen.

Angenommen folgende Implementierung (Scott Meyers Singleton):
static Singleton& instance()
{
     static Singleton s;
     return s;
}

Das ganze als Klassenfunktion eines Singleton-templates (macht nur 
Konstruktor/Copy Constructor + Assignment private) gebaut zu
static T & Singleton<T>::instance()
{
     static T s;
     return s;
}

Jetzt instanziiert man einfach zwei verschiedene Singletons mit 
Datentypen, die zur Konstruktionszeit voneinander abhängig sind. 
Passiert in gewachsenem Code sogar manchmal fast zufällig.
Foo & foo( Singleton<Foo>()::instance() );
Bar & bar( Singleton<Bar>()::instance() );

Referenziert 'Foo' irgendwie durch 'ne Member 'Bar' über diese 
Singleton-Implementierung, kracht es. Bzw. es wird vollkommen 
undurchschaubar, wann welches Singleton-Objekt zuerst entsteht.

Daher lieber durch'n Konstruktor die Abhängigkeiten klären und auf 
solchen Singleton-Sch**ß verzichten:
Bar::Bar( Foo & foo );

Autor: db8fs (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bzw. was ich sagen will, aber irgendwie nicht so richtig rauskommt: das 
Konzept "lokal geht vor global" kann durch solchen static-Kram 
unterwandert werden, egal nun ob durch Klassenmember oder lokale 
static-Variablen.

'ne RaceCondition zur Konstruktionszeit kann man also auch so 
hinkriegen, man muss nur eine Resource unnötig global machen.

Autor: Rolf M. (rmagnus)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
db8fs schrieb:
> Referenziert 'Foo' irgendwie durch 'ne Member 'Bar' über diese
> Singleton-Implementierung, kracht es. Bzw. es wird vollkommen
> undurchschaubar, wann welches Singleton-Objekt zuerst entsteht.

Was ist das Problem? Bar wird instanziiert, wenn es zum ersten mal 
benutzt wird. Wenn Foo Bar braucht, wird es eben genau dort 
instanziiert. Wenn du ein Singleton verwendest, sollte dir auch egal 
sein, ob es schon existiert oder erst in dem Moment erzeugt werden muss. 
Das passiert ja schließlich im Hintergrund.

db8fs schrieb:
> Daher lieber durch'n Konstruktor die Abhängigkeiten klären und auf
> solchen Singleton-Sch**ß verzichten:
>
> Bar::Bar( Foo & foo );

Ich sehe nicht, wie das jetzt Singletons vollständig ersetzen soll. Das 
ist doch nur ein Konstruktor. Wo, wie und wann die Objekte erzeugt 
werden, fehlt noch.

Autor: db8fs (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Rolf M. schrieb:
> db8fs schrieb:
>> Referenziert 'Foo' irgendwie durch 'ne Member 'Bar' über diese
>> Singleton-Implementierung, kracht es. Bzw. es wird vollkommen
>> undurchschaubar, wann welches Singleton-Objekt zuerst entsteht.
>
> Was ist das Problem? Bar wird instanziiert, wenn es zum ersten mal
> benutzt wird. Wenn Foo Bar braucht, wird es eben genau dort
> instanziiert. Wenn du ein Singleton verwendest, sollte dir auch egal
> sein, ob es schon existiert oder erst in dem Moment erzeugt werden muss.
> Das passiert ja schließlich im Hintergrund.

Hmm, eben das ist halt leider nicht egal, wenn man sicherstellen muss, 
dass die Objekte nur innerhalb eines gewissen Threadkontextes existieren 
dürfen, z.B. UI-Thread. Hat man nur einen Thread, haste 100% recht.

> Ich sehe nicht, wie das jetzt Singletons vollständig ersetzen soll. Das
> ist doch nur ein Konstruktor. Wo, wie und wann die Objekte erzeugt
> werden, fehlt noch.

Na ja, nee. Ein Singleton ist immer ein querschnittlicher, globaler 
Ansatz durch die gesamte Applikation hindurch. Es ist zudem eine harte 
Einschränkung auf eine Klasse, indem höchstens eine Instanz davon 
erlaubt wird.

Semantisch äquivalent zur obigen Singleton-Implementierung wäre es ja, 
einfach im top-level-Objekt der Applikation (z.B. Klasse 'Plugin') 
Instanzen von Foo und Bar anzulegen. Und um Foo anlegen zu können, muss 
halt vorher Bar da sein.

Wenns halt nicht anders geht, außer durch globalen Zugriff, muss sich 
dann ein Foo bzw. Bar-Referenzierender aus einer anderen Klasse über das 
Top-Level-Objekt die Instanz holen.

Geht aber alles ohne static und ohne Singleton.

Autor: mh (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
db8fs schrieb:
> Referenziert 'Foo' irgendwie durch 'ne Member 'Bar' über diese
> Singleton-Implementierung, kracht es. Bzw. es wird vollkommen
> undurchschaubar, wann welches Singleton-Objekt zuerst entsteht.

Kannst du ein vollständiges Beispiel geben, bei dem es durch Probleme 
mit der Initialisierungsreihenfolge kracht?

Autor: Wilhelm M. (wimalopaan)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
mh schrieb:
> db8fs schrieb:
>> Referenziert 'Foo' irgendwie durch 'ne Member 'Bar' über diese
>> Singleton-Implementierung, kracht es. Bzw. es wird vollkommen
>> undurchschaubar, wann welches Singleton-Objekt zuerst entsteht.
>
> Kannst du ein vollständiges Beispiel geben, bei dem es durch Probleme
> mit der Initialisierungsreihenfolge kracht?

Vielleicht meint er das "static initialization fiasco"?

Autor: db8fs (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
mh schrieb:
> Kannst du ein vollständiges Beispiel geben, bei dem es durch Probleme
> mit der Initialisierungsreihenfolge kracht?

Kann ich machen, dauert 'nen Moment.

Autor: mh (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wilhelm M. schrieb:
> Vielleicht meint er das "static initialization fiasco"?

Dieses fiasco existiert aber nicht, wenn man diese, von ihm als Scott 
Mayers Singleton bezeichnete, Methode benutzt.

Autor: Wilhelm M. (wimalopaan)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
mh schrieb:
> Wilhelm M. schrieb:
>> Vielleicht meint er das "static initialization fiasco"?
>
> Dieses fiasco existiert aber nicht, wenn man diese, von ihm als Scott
> Mayers Singleton bezeichnete, Methode benutzt.

Ok, da habe ich seinen Satz
Referenziert 'Foo' irgendwie durch 'ne Member 'Bar' über diese 
Singleton-Implementierung, kracht es. Bzw. es wird vollkommen 
undurchschaubar, wann welches Singleton-Objekt zuerst entsteht.
falsch verstanden bzw. jetzt erst richtig gelesen ... sorry for the 
noise.

: Bearbeitet durch User
Autor: db8fs (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das Konstruktionszeit-Problem entsteht genau dann, wenn man nicht 
beliebige Initialisierungszeitpunkte für das Singleton zulässt bzw. 
zulassen darf, weil ein Objekt sonst im falschen Thread-Local-Storage 
oder so landen kann.


Also sprich, wenn man sicherstellen muss, dass es genau ein Objekt 
gibt, dass zu genau einem definierten Zeitpunkt entsteht.

Neben Thread-Problematiken kann das auch für teuer zu erstellende 
Objekte eine Rolle spielen, insbesondere mit dem Idiom "Resource 
Allocation is Initialization" könnte das eine Rolle spielen.

D.h. das mal auf ein Beispiel übertragen: Singleton + Einschränkung des 
Konstruktionszeitpunktes zur Laufzeit für das eine Objekt.

Folgendes müsste eigentlich zu einer Null-Pointer-Dereferenzierung 
führen, wenn man den Konstruktionszeitpunkt einschränkt:
#include <iostream>

template <class T>
class Singleton
{

public:
        // instance operator, converted to dynamic memory allocation for definining initialization time
        static T & instance( bool init=false )
        {
                static T* obj( NULL );

                if( init )
                {
                        obj = new T();
                }

                return *obj;
        }


        // memleak ignored for this example
};


class Bar
{
        friend class Singleton<Bar>;

        Bar()
        {
        }

public:
        void print() { std::cout << "bar" << std::endl; }

};


class Foo
{
        friend class Singleton<Foo>;

        Foo()
        {
                // null pointer dereference when constructed in wrong order
                Singleton<Bar>::instance( false ).print();
        }
};



int main(int argc, char** argv)
{

  Foo & foo( Singleton<Foo>::instance( true ) );
  Bar & bar( Singleton<Bar>::instance( true ) );

  return 0;
}

Autor: db8fs (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ok, eigentlich doof, da Bar::print() zustandslos ist, bei Bedarf (wenns 
halt noch nicht kracht), halt 'ne Abhängigkeit zum Objektzustand in das 
print() reintun.

Also z.B. ne std::string-Member in Bar hinzufügen, deren Text im print() 
ausgegeben wird.

Autor: db8fs (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
mh schrieb:
> Wilhelm M. schrieb:
>> Vielleicht meint er das "static initialization fiasco"?
>
> Dieses fiasco existiert aber nicht, wenn man diese, von ihm als Scott
> Mayers Singleton bezeichnete, Methode benutzt.

Im Prinzip haste recht damit - zumindest in 'ner idealen Welt frei von 
jeglicher Nebenläufigkeit bzw. frei von Allokationsängsten.

Solche technischen Sorgen können allerdings trotz Verwendung des Idioms 
Probleme entstehen lassen. Z.B. wenn eine Callback aus einem anderen 
Threadkontext von einer Nachbarkomponente das Objekt zuerst 
initialisieren würde - z.B. durch blödes Timing.

Hab zwar keine große Ahnung von .NET/Java, könnte mir aber vorstellen, 
dass auch da der GarbageCollector nicht immer perfekt mitspielen könnte 
- trotz des Meyers-Idioms.

Autor: Rolf M. (rmagnus)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
db8fs schrieb:
> Folgendes müsste eigentlich zu einer Null-Pointer-Dereferenzierung
> führen, wenn man den Konstruktionszeitpunkt einschränkt:

Wobei man das so natürlich niemals programmieren würde.
Für mich ist das für ein "normales" Singleton eine Grundvoraussetztung, 
dass der Initialisierungszeitpunkt und ggf. -thread nicht wichtig ist, 
solange es vor der ersten Verwendung initialisiert ist. Wenn es da 
Einschränkungen gibt, muss man sich darum zusätzlich kümmern. Aber das 
muss man auch ohne Singleton.

Autor: db8fs (Gast)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Rolf M. schrieb:
> Wobei man das so natürlich niemals programmieren würde.
> Für mich ist das für ein "normales" Singleton eine Grundvoraussetztung,
> dass der Initialisierungszeitpunkt und ggf. -thread nicht wichtig ist,
> solange es vor der ersten Verwendung initialisiert ist. Wenn es da
> Einschränkungen gibt, muss man sich darum zusätzlich kümmern. Aber das
> muss man auch ohne Singleton.

:D
Wahre Worte - aber du kennst es sicher aus eigener Erfahrung, der 
"Goldene Hammer" funktioniert oft sehr gut, z.B. in der Gestalt der 
weisen Lehren aus'm Buch, die auf die eigenen Anwendungen angewendet 
werden und wo man dann feststellt, dass halt irgendwas doch nicht ganz 
passt.

Der Code oben ist auch schon paar Jahre alt, an den Architektursünden, 
die durch die Singletons entstanden sind, hatte ich lange geknabbert, 
bis die raus waren.

Bin heute sogar der Meinung, dass Singleton-Verwendungen häufige 
Indizien für unvorteilhafte Architekturen sind.

Autor: mh (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Rolf M. schrieb:
> Wenn es da Einschränkungen gibt, muss man sich darum zusätzlich kümmern.
Und zwar explizit und offensichtlich.

Autor: Rolf M. (rmagnus)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
db8fs schrieb:
> Bin heute sogar der Meinung, dass Singleton-Verwendungen häufige
> Indizien für unvorteilhafte Architekturen sind.

Meine Erfahrung ist, dass zu viel Verwendung von Singletons dazu führt, 
dass der Code nicht mehr richtig modular ist. Überall kreuz und quer im 
Code hat man Abhängigkeiten. Letztendlich genau die Probleme, wegen 
derer globale Variablen so verpönt sind.

Autor: Nase (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
db8fs schrieb:
> Folgendes müsste eigentlich zu einer Null-Pointer-Dereferenzierung
> führen, wenn man den Konstruktionszeitpunkt einschränkt:

Das, was du in diesem Beispiel gemacht hast, ist aber ja *gerade kein 
Singleton*. Es ist einfach nur eine globale Variable, die in einer 
statischen  Methode verpackt wurde.

Duch die if-Abfrage mit dem "init"-Parameter hast du ja quasi alles 
ausgehebelt, was ein Singleton normalerweise tut: Nämlich die Ressource 
genau einmalig bei Anforderung anlegen. Dein Dingen da legt die 
Ressource aber nicht implizit bei Anforderung an, sondern nur explizit 
(wenn "init" == true ist).

Natürlich kracht das. Das ist halt kein Singleton.
Hast du ja auch völlig richtig erklärt.

Autor: db8fs (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nase schrieb:
> Das, was du in diesem Beispiel gemacht hast, ist aber ja *gerade kein
> Singleton*. Es ist einfach nur eine globale Variable, die in einer
> statischen  Methode verpackt wurde.

Ok, einverstanden, es ist eine globale Variable, die über den 
template-Wrapper global zugänglich wird.

Gegenfrage: was ist denn das einzig wahre Singleton für C++?

> Duch die if-Abfrage mit dem "init"-Parameter hast du ja quasi alles
> ausgehebelt, was ein Singleton normalerweise tut: Nämlich die Ressource
> genau einmalig bei Anforderung anlegen.

Ok, wie stellst du sonst in C++ sicher, dass höchstens ein Exemplar der 
Klasse zur Laufzeit existiert? Find das interessant und lass mich gerne 
eines besseren Ansatzes belehren.

> Dein Dingen da legt die
> Ressource aber nicht implizit bei Anforderung an, sondern nur explizit
> (wenn "init" == true ist).

Jo, haste recht. Mit dem Hintergrundverweis auf die 
C++-Laufzeitumgebung, welche für obige Verwendung (Multithreading, Calls 
von anderen Plugins) halt Restriktionen auf die Implementierung 
auferlegt. Zumindest was die Initialisierung betrifft. Ist halt so.

> Natürlich kracht das. Das ist halt kein Singleton.
Schön, wenn das natürlich so ist - wie wäre denn die richtige Lösung?

Autor: Johann L. (gjlayde) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
db8fs schrieb:
> Mit dem Hintergrundverweis auf die  C++-Laufzeitumgebung, welche
> für obige Verwendung (Multithreading, Calls
> von anderen Plugins) halt Restriktionen auf die Implementierung
> auferlegt. Zumindest was die Initialisierung betrifft.

Die Initialisierung ist zumindest Thread-safe, so dass ein Static 
höchstens 1× initialisiert wird und auch nicht konkurrierend von 
mehreren Threads.  Schau mal den generierten Code an für ein 
nicht-triviales Beispiel, also für eines, wo das const nicht in .rodata 
liegt und erst zu Laufzeit initialisiert wird.

Autor: Wilhelm M. (wimalopaan)
Datum:

Bewertung
3 lesenswert
nicht lesenswert
Zum Thema local statics und Nebenläufigkeit (s.a. 
http://eel.is/c++draft/stmt.dcl, oder 
http://en.cppreference.com/w/cpp/language/storage_duration):
Dynamic initialization of a block-scope variable with static storage duration or thread storage duration is performed the first time control passes through its declaration; such a variable is considered initialized upon the completion of its initialization. If the initialization exits by throwing an exception, the initialization is not complete, so it will be tried again the next time control enters the declaration. If control enters the declaration concurrently while the variable is being initialized, the concurrent execution shall wait for completion of the initialization.

Ist also ganz klar geregelt.

Die "alte" Variante verlangt etwas mehr "Aufmerksamkeit":

http://www.aristeia.com/Papers/DDJ_Jul_Aug_2004_revised.pdf

Das Paper ist m.E. der Grund, warum dieser o.g. Passus explizit in C++11 
aufgenommen wurde.

Autor: Nase (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wilhelm M. schrieb:
> Das Paper ist m.E. der Grund, warum dieser o.g. Passus explizit in C++11
> aufgenommen wurde.
Und es ist eines der besten Papers zum Thema.

db8fs schrieb:
> Gegenfrage: was ist denn das einzig wahre Singleton für C++?
Nun werde doch nicht dogmatisch.
Der Kerngedanke des Singleton-Patterns ist (war zumindest früher), eine 
Ressource schludrig (lazu) bereitzustellen, nämlich bei Anforderung. 
Diese Festlegung deckt sich mit allen mir bekannten Lektüren über 
Entwurfsmuster.
Also genau das, was du da nicht machst, denn du initialisierst die 
Instanz ja gerade explizit und zum Programmstart.

db8fs schrieb:
> Ok, wie stellst du sonst in C++ sicher, dass höchstens ein Exemplar der
> Klasse zur Laufzeit existiert? Find das interessant und lass mich gerne
> eines besseren Ansatzes belehren.
struct TheObject { };

struct Singleton {
    static TheObject *getTheObject() {
        static TheObject instance;
        return &instance;
    }
};

Spätestens seit C++11 ist das sogar thread-wasserdicht.

Autor: Friedelbär (Gast)
Datum:

Bewertung
2 lesenswert
nicht lesenswert
Ich versteh mittlerweile nur noch Bahnhof und wünschte ich würde mehr 
von C++ verstehen :-)

Beitrag #5258532 wurde von einem Moderator gelöscht.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.