C++: char* behält zugewiesenen wert und std::string nimmt default an... wieso?
bearbeitet von Rolf BHallo hmm,
was Du da vorhast, ist ein Unfall der darauf wartet zu passieren. Grund: Statische Elemente einer Klasse werden nicht von ihrem Destruktor beeinflusst. Warum auch - es ist sinnlos bis falsch, beim Zerstören einer Instanz auch die statischen Elemente zu beseitigen.
D.h. du bist in deinem Destruktor auf die richtige Anordnung des Sourcecodes angewiesen, wenn Du auf irgendwas zugreifen willst, das nicht Teil dieser Klasseninstanz ist. Konstruktion und
Destruktion erfolgen in entgegengesetzter Reihenfolge, das ist ein Stack, und weil du erst Bla erzeugst und dann a, wird zuerst a vernichtet und dann Bla.
Das Konstrukt `class Bla {...} Bla;` macht dreierlei: Es definiert (1) die Klasse Bla, (2) allociert es eine Variable namens `Bla` vom Typ `class Bla` und (3) registriert es diese Variable zur Destruktion. Erst nach wird eine Variable a vom Typ std:string deklariert, ein Objekt vom Typ std:string erzeugt und mit einem Leerstring initialisiert.
Trenne die Deklaration von class Bla und die Allocation der Variablen Bla, dann gehts:
~~~cpp
class Bla
{
public:
static std::string a;
static std::char* b;
~Bla()
{
printf(a);
printf(b);
}
};
std::string Bla::a = "";
std::char* Bla::b = "
Bla Bla;
irgendEinKlasse::FunktionDieAufgerufenWird()
{
Bla::a = "test";
Bla::b = "test";
}
~~~
Ich würde Dir aber eigentlich empfehlen wollen, das so nicht zu tun. Du schaffst damit implizite Abhängigkeiten, die auf der lexikalischen Reihenfolge der Elemente im Code basieren. Es ist robuster, solche Abhängigkeiten explizit zu machen.
D.h. statt eines static-Members a verwende ein non-static Member. Das ist dann eine normale Eigenschaft der Bla-Klasse, du kannst sie im Konstruktor von Bla initialisieren und dann ist eindeutig klar, dass es erst nach Ende des Destruktors von Bla zerstört wird.
Alle Zugriffe auf deine Map lässt Du dann über die Bla Variable laufen (für die du sicherlich noch einen besseren Namen findest, und Du solltest vielleicht auch Abstand davon nehmen, Klassen und Variablen gleich zu benennen - mich hat das erstmal verwirrt.
Tja, und wenn Du das Ende des Programms finden musst - was für ein Typ von Programm ist das denn? Du hast doch normalerweise immer irgendeine main() Funktion. Wenn die endet, endet auch das Programm.
_Rolf_
--
sumpsi - posui - clusi
C++: char* behält zugewiesenen wert und std::string nimmt default an... wieso?
bearbeitet von Rolf BHallo hmm,
was Du da vorhast, ist ein Unfall der darauf wartet zu passieren. Grund: Statische Elemente einer Klasse werden nicht von ihrem Destruktor beeinflusst. Warum auch - es ist sinnlos bis falsch, beim Zerstören einer Instanz auch die statischen Elemente zu beseitigen.
D.h. du bist in deinem Destruktor auf die richtige Anordnung des Sourcecodes angewiesen, wenn Du auf irgendwas zugreifen willst, das nicht Teil dieser Klasseninstanz ist. Konstruktion und
Destruktion erfolgen in entgegengesetzter Reihenfolge, das ist ein Stack, und weil du erst Bla erzeugst und dann a, wird zuerst a vernichtet und dann Bla.
Das Konstrukt `class Bla {...} Bla;` macht dreierlei: Es definiert (1) die Klasse Bla, (2) allociert es eine Variable namens `Bla` vom Typ `class Bla` und (3) registriert es diese Variable zur Destruktion. Erst nach wird eine Variable a vom Typ std:string deklariert, ein Objekt vom Typ std:string erzeugt und mit einem Leerstring initialisiert.
Trenne die Deklaration von class Bla und die Allocation der Variablen Bla, dann gehts:
~~~cpp
class Bla
{
public:
static std::string a;
static std::char* b;
~Bla()
{
printf(a);
printf(b);
}
};
std::string Bla::a = "";
std::char* Bla::b = "
Bla Bla;
irgendEinKlasse::FunktionDieAufgerufenWird()
{
Bla::a = "test";
Bla::b = "test";
}
~~~
Ich würde Dir aber eigentlich empfehlen wollen, das so nicht zu tun. Du schaffst damit implizite Abhängigkeiten, die auf der lexikalischen Reihenfolge der Elemente im Code basieren. Es ist robuster, solche Abhängigkeiten explizit zu machen.
D.h. statt eines static-Members a verwende ein non-static Member. Das ist dann eine normale Eigenschaft der Bla-Klasse, und dann ist eindeutig klar, dass es erst nach Ende des Destruktors von Bla zerstört wird.
Alle Zugriffe auf deine Map lässt Du dann über die Bla Variable laufen (für die du sicherlich noch einen besseren Namen findest, und Du solltest vielleicht auch Abstand davon nehmen, Klassen und Variablen gleich zu benennen - mich hat das erstmal verwirrt.
Tja, und wenn Du das Ende des Programms finden musst - was für ein Typ von Programm ist das denn? Du hast doch normalerweise immer irgendeine main() Funktion. Wenn die endet, endet auch das Programm.
_Rolf_
--
sumpsi - posui - clusi
C++: char* behält zugewiesenen wert und std::string nimmt default an... wieso?
bearbeitet von Rolf BHallo hmm,
was Du da vorhast, ist ein Unfall der darauf wartet zu passieren. Grund: Statische Elemente einer Klasse werden nicht von ihrem Destruktor beeinflusst. Warum auch - es ist sinnlos bis falsch, beim Zerstören einer Instanz auch die statischen Elemente zu beseitigen.
D.h. du bist in deinem Destruktor auf den guten Willen des Compilers angewiesen, wenn Du auf irgendwas zugreifen willst, das nicht Teil dieser Klasseninstanz ist. Die Reihenfolge der Destruktion von Bla und a ist zufällig. D.h. vermutlich ist es das nicht ganz, die Destruktion erfolgt üblicherweise "rückwärts", und weil du erst Bla erzeugst und dann a, wird zuerst a vernichtet und dann Bla.
Das Konstrukt `class Bla {...} Bla;` macht dreierlei: Es definiert (1) die Klasse Bla, (2) allociert es eine Variable namens `Bla` vom Typ `class Bla` und (3) registriert es diese Variable zur Destruktion. Erst nach wird eine Variable a vom Typ std:string deklariert, ein Objekt vom Typ std:string erzeugt und mit einem Leerstring initialisiert.
Trenne die Deklaration von class Bla und die Allocation der Variablen Bla, dann gehts:
~~~cpp
class Bla
{
public:
static std::string a;
static std::char* b;
~Bla()
{
printf(a);
printf(b);
}
};
std::string Bla::a = "";
std::char* Bla::b = "
Bla Bla;
irgendEinKlasse::FunktionDieAufgerufenWird()
{
Bla::a = "test";
Bla::b = "test";
}
~~~
Ich würde Dir aber eigentlich empfehlen wollen, das so nicht zu tun. Du schaffst damit implizite Abhängigkeiten, die auf der lexikalischen Reihenfolge der Elemente im Code basieren. Es ist besser, solche Abhängigkeiten explizit zu machen.
D.h. statt eines static-Members a verwende ein non-static Member. Das ist dann eine normale Eigenschaft der Bla-Klasse, und dann ist eindeutig klar, dass es erst nach Ende des Destruktors von Bla zerstört wird.
Alle Zugriffe auf deine Map lässt Du dann über die Bla Variable laufen (für die du sicherlich noch einen besseren Namen findest, und Du solltest vielleicht auch Abstand davon nehmen, Klassen und Variablen gleich zu benennen - mich hat das erstmal verwirrt.
Tja, und wenn Du das Ende des Programms finden musst - was für ein Typ von Programm ist das denn? Du hast doch normalerweise immer irgendeine main() Funktion. Wenn die endet, endet auch das Programm.
_Rolf_
--
sumpsi - posui - clusi