2012-05-16 6 views
7

Initialisierung habe ich eine Klasse mit einem statischen Element, das einen Zeiger wie so ist:einen statischen Zeiger in C++

animation.h

class Animation 
{ 
public: 
    Animation(); 
    static QString *m; 

}; 

animation.cpp

#include "animation.h" 

QString* Animation::m = 0; 

Animation::Animation() 
{ 
} 

Wenn ich versuche, um diesen "m" -Zeiger von einer anderen Klasse wie diesem zu initialisieren:

Animation::m = new QString("testing"); 

Es funktioniert.

Aber wenn ich es so:

QString x("Testing"); 
Animation::m = &x; 

Das Programm stürzt ab.

Was ist falsch an dieser zweiten Methode?

Auch ich möchte diesen statischen Zeiger als privat haben, damit ich statische Getter- und Setter-Funktionen machen kann. Der Setzer sollte die zweite Methode verwenden, da das 'x' in einem Parameter kommt, so dass ich feststecke.

Danke für jede Hilfe!

Antwort

12

Ich wette, es stürzt nicht auf dieser Linie, aber danach.

Das Problem ist, dass Sie die Adresse einer Variablen im automatischen Speicher nehmen, und versuchen Sie wahrscheinlich, danach darauf zuzugreifen. Die Variable x wird zerstört, wenn das Oszilloskop beendet ist, aber Animation::m zeigt immer noch auf diesen Speicher (Speicher, den Sie nicht mehr besitzen, nachdem x den Gültigkeitsbereich verlassen hat). Dies führt zu undefiniertem Verhalten.

Genau wie die folgende illegal wäre:

int* x = NULL; 
{ 
    int k = 3; 
    x = &k; 
} 
*x = 4; 

Behelfslösung auf den Wert zuzuweisen, den Zeiger nicht (vorausgesetzt, es ist zuvor auf einen gültigen QString* zugewiesen wurde):

QString x("Testing"); 
*(Animation::m) = x; 
+0

Das definitiv beantwortet es danke! –

+0

'* (Animation :: m) = x;' verfälscht einen '0' Zeiger.Der Zeiger wurde nie zugewiesen, er wurde nur auf' 0' initialisiert. –

+0

@Als verpasst, korrigiert. Vielen Dank. –

2

Was ist falsch an dieser zweiten Methode?

Es stürzt ab, weil Sie höchstwahrscheinlich auf es außerhalb des Bereichs zugreifen, in dem x erstellt wurde.

Automatische Variablen werden automatisch zerstört, sobald das Steuerelement den Gültigkeitsbereich {}, in dem sie erstellt wurden, verlässt. Also über den Rahmen hinaus, was Sie haben, ist ein Zeiger auf Daten, die nicht existiert. Der Zugriff auf diese Daten führt zu einem nicht definierten Verhalten und einem Absturz.

Wie geht es?

Sie sollten Speicher dynamisch zuweisen und dann die Zeichenfolge in den dynamisch zugewiesenen Zeiger kopieren, damit Sie überall darauf zugreifen können. Auf diese Weise bleibt die Zeichenfolge gültig, es sei denn, und bis explizit delete Ed.

1

Ich wette, dass Ihr Programm abstürzt, wenn Sie Animation::m verwenden, nachdem x zerstört wurde (wahrscheinlich durch den Geltungsbereich).

Wenn Sie einen Setter verwenden möchten Animation::m zuweisen, werden Sie als Zeiger oder durch Bezugnahme in dem Argument übergeben müssen:

class Animation 
{ 
public: 
    Animation(); 

    void set_m(QString* ptr) { 
     m = ptr; 
    } 

    void set_m(QString& ref) { 
     m = &ref; 
    } 

private: 
    static QString *m; 

}; 

Allerdings müssen Sie noch dafür sorgen, dass was auch immer m Punkte immer noch am Leben ist, wenn Sie versuchen, m zu verwenden.