2010-07-15 23 views
7

È necessario inserire i puntatori di classi (ereditati da QObject) in una QList. So che la seguente sintassi può essere utilizzato:Aggiunta di puntatori a QList

.h

QList<MyObject*> list; 

cpp

list.append(new MyObject("first", 1)); 
list.append(new MyObject("second", 2)); 
... 

e quindi liberare la memoria:

if(!list.isEmpty()) 
{ 
    qDeleteAll(list); 
    list.clear(); 
} 

Questo dovrebbe sii valido e lo fa non causa alcuna perdita di memoria (per quanto ne so). Tuttavia, ho bisogno di inizializzare gli oggetti prima di aggiungerli alla collezione. Può la seguente parte di codice causare alcuni errori come perdite di memoria o puntatori penzolanti (userò allo stesso modo per eliminare i puntatori come sopra)?

MyObject *obj; 

for(i = 0; i < 5; i++) 
{ 
    obj = new MyObject(); 
    if(!obj.Init(i, map.values(i))) 
    { 
     // handle error 
    } 
    else 
    { 
     list.append(obj); 
    } 
} 

Grazie.

+1

solo una nota: il caso (list.isEmpty()) quando si utilizza qDeleteAll() è ridondante, lo ometterei. –

risposta

4

se si prende cura di "obj" (l'istanza allocata ma non inizializzato) in caso di "errore // manico", il codice è ok.

0

Utilizzare RAII (l'allocazione delle risorse è l'inizializzazione). Inizializza direttamente l'oggetto nel costruttore.

Quindi il codice sarebbe simile:

for(i = 0; i < 5; i++) 
{ 
    list.append(new MyObject(i, map.values(i))); 
    // In case of initialization failure, throw exception from the constructor 
} 
+2

cosa succede se nel suo ambiente non sono ammesse eccezioni? – akira

+0

... quindi è necessario trovare un altro meccanismo per segnalare errori. Potrebbe essere qualcosa come una funzione "getLastError" (forse thread-safe). Ma perché ipotizzare eccezioni non permesse? Non c'è nulla di menzionato nella domanda, quindi l'ho mantenuto semplice. –

+0

Lanciare un'eccezione era in effetti sotto la mia considerazione. In caso di errore di inizializzazione, desidero ricevere un messaggio di errore dall'oggetto per scopi di debug (attualmente utilizzando il metodo pubblico obj.getError()). So che è possibile segnalare errori con eccezioni (ad esempio lanciando una stringa), ma attualmente sto giocando con valori di ritorno e messaggi di errore (come le librerie Qt) e vorrei rimanere su quella strada. Questo è il motivo principale per cui ho chiesto se il codice di quest'ultimo è valido. – Routa

0

È possibile utilizzare QScopedPointer ..

Dal 4.6 documentazione Qt,

I negozi di classe QScopedPointer un puntatore ad un oggetto allocato dinamicamente, e cancella su di distruzione. La gestione manuale degli oggetti allocati nell'heap è difficile e soggetta a errori, con il comune risultato che il codice perde memoria ed è difficile da mantenere. QScopedPointer è una piccola classe di utilità che semplifica notevolmente questa operazione assegnando la proprietà della memoria basata su stack all'heap delle allocazioni, più in generale denominata acquisizione delle risorse (RAII).

Speranza che aiuta ..

Edit:

Per esempio,

si intende utilizzare,

QScopedPointer<QWidget> p(new QWidget()); 

invece di

QWidget *p = new QWidget(); 

e aggiungi QScopedPointer nel tuo QList senza preoccuparti di perdite di memoria e .

+0

in modo che il ciclo interno assomigli a questo: QScopedPointer obj (new MyObject()); if (obj-> Init (map.values ​​(i)) {list.append (obj.take());} ... aggiungilo per rispondere per vedere il vantaggio – akira

+0

scusa non ho capito il tuo esempio. ho appena aggiunto un esempio di base dai documenti per chiarire le cose .. Io aggiungo questo prima con la speranza che la gente lo troverà comunque dai documenti .. :) – liaK

+0

quale parte del mio esempio essenzialmente di 3 righe non è chiara? btw, il tuo esempio condurrà a un segfault, perché l'ambito ptr continua a OWNS l'istanza, ecco perché ho usato .take(). – akira

3

Utilizzare invece QSharedPointer.

QList<QSharedPointer<MyObject> > list; 

Per liberare memoria è sufficiente fare

if(!list.isEmpty()) 
{ 
    list.clear(); 
} 

da aggiungere a elencare

list.append(QSharedPointer<MyObject>(new MyObject("first", 1))); 
list.append(QSharedPointer<MyObject>(new MyObject("second", 2)));