2012-05-16 3 views
7

Ho una classe con un membro statico che è un puntatore in questo modo:inizializzazione di un puntatore statica in C++

animation.h

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

}; 

animation.cpp

#include "animation.h" 

QString* Animation::m = 0; 

Animation::Animation() 
{ 
} 

Quando provo per inizializzare quel puntatore "m" di un'altra classe in questo modo:

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

Funziona.

Ma quando lo faccio in questo modo:

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

il programma si blocca.

Cosa c'è di sbagliato in questo secondo metodo?

Anche io vorrei avere quel puntatore statico come privato in modo da poter fare funzioni getter e setter statiche ad esso. Il setter dovrebbe usare il secondo metodo poiché la 'x' arriverà in un parametro quindi sono bloccato.

Grazie per qualsiasi aiuto!

risposta

12

Scommetto che non sta andando su quella linea, ma dopo.

Il problema è che si sta prendendo l'indirizzo di una variabile che si trova nella memoria automatica e probabilmente si tenta di accedervi in ​​seguito. La variabile x verrà distrutta al termine dell'ambito, ma Animation::m continuerà a puntare a quella memoria (memoria che non si possiede più dopo lo x andato fuori ambito). Ciò comporta il comportamento non definito .

Proprio come la seguente sarebbe illegale:

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

Soluzione assegnare al valore, non il puntatore (a condizione che è stato precedentemente assegnato a una valida QString*):

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

Che sicuramente risponde grazie! –

+0

'* (Animation :: m) = x;' deferenze un puntatore '0'. Il puntatore non è mai stato assegnato è stato inizializzato su' 0'. –

+0

@Per mancare quello, corretto. Grazie. –

2

Cosa c'è di sbagliato in questo secondo metodo?

Si arresta in modo anomalo perché molto probabilmente lo si accede oltre lo scopo in cui è stato creato x.

Le variabili automatiche vengono automaticamente distrutte quando il controllo esce dall'ambito {} in cui sono state create. Quindi, oltre lo scopo, quello che si ha è un puntatore che punta a dati che non esistono. L'accesso a questi dati causa un comportamento non definito e un arresto anomalo.

Come procedere?

È necessario allocare dinamicamente la memoria e quindi copiare la stringa sul puntatore allocata dinamicamente in modo che sia possibile accedervi ovunque. In questo modo la stringa rimane valida a meno che e fino a quando non esplicitamente delete ed.

1

Scommetto che il programma si blocca quando si utilizza Animation::m dopo che x è stato distrutto (probabilmente uscendo dall'ambito).

Se si desidera utilizzare un setter per assegnare a Animation::m, è necessario passare l'argomento come un puntatore o per riferimento:

class Animation 
{ 
public: 
    Animation(); 

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

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

private: 
    static QString *m; 

}; 

Tuttavia, è ancora necessario fare in modo che qualunque cosa punti m è ancora attiva quando si tenta di utilizzare m.