2010-07-15 24 views
7

Necesito insertar punteros de clases (heredados de QObject) en una QList. Sé que la siguiente sintaxis se puede utilizar:Adjuntar punteros a QList

.h

QList<MyObject*> list; 

.cpp

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

y luego liberar memoria:

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

Esto debería ser válido y lo hace no causa ninguna pérdida de memoria (por lo que yo sé). Sin embargo, necesito inicializar objetos antes de agregarlos a la colección. ¿Puede el siguiente fragmento de código causar algunos errores, como fugas de memoria o punteros colgantes (lo utilizaré de la misma manera para eliminar los punteros que los anteriores)?

MyObject *obj; 

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

Gracias.

+1

sólo una nota: si el (list.isEmpty()) cuando se utiliza qDeleteAll() es redundante, simplemente lo omitiría. –

Respuesta

4

si se cuida de "obj" (la instancia asignados, pero no inicializado) en el caso de "error // manipulador", su código es aceptable.

0

Use RAII (Asignación de recursos es inicialización). Inicializa el objeto en el constructor directamente.

continuación, el código se vería así:

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

¿qué pasa si las excepciones no están permitidas en su entorno? – akira

+0

... luego debe encontrarse otro mecanismo para informar errores. Puede ser algo así como una función "getLastError" (quizás thread safe). Pero ¿por qué asumir excepciones no permitidas? No hay nada mencionado en la pregunta, así que lo mantuve simple. –

+0

Lanzar una excepción era de hecho bajo mi consideración. En caso de error de inicialización, deseo recibir un mensaje de error del objeto para fines de depuración (actualmente usando el método público obj.getError()). Sé que es posible informar errores con excepciones (por ejemplo, lanzar una cadena), pero actualmente estoy jugando con valores devueltos y mensajes de error (como bibliotecas Qt) y me gustaría permanecer en ese camino. Esa es la razón principal por la que pregunté si el último código está bien. – Routa

0

Puede utilizar QScopedPointer ..

A partir de la documentación de Qt 4.6,

Las tiendas de clase QScopedPointer un puntero a un objeto asignado dinámicamente, y lo elimina en la destrucción. Administrar objetos asignados en el montón de forma manual es difícil y propenso a errores, con el resultado común de que el código pierde memoria y es difícil de mantener. QScopedPointer es una pequeña clase de utilidad que simplifica enormemente esto asignando la propiedad de la memoria basada en la pila a las asignaciones del montón, más generalmente llamada adquisición de recursos es la inicialización (RAII).

creo que sirve ..

Editar:

Por ejemplo,

que va a utilizar,

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

en lugar de

QWidget *p = new QWidget(); 

y agregue el QScopedPointer en su QList sin preocuparse por pérdida de memoria y punteros colgantes.

+0

por lo que el bucle interno se ve así: QScopedPointer obj (nuevo MyObject()); if (obj-> Init (map.values ​​(i)) {list.append (obj.take());} ... agrégalo a la respuesta para ver la ventaja. – akira

+0

lo siento, no pude entender tu ejemplo. se agregó un ejemplo básico de los documentos a dejar las cosas claras .. me fuerza agregan esto antes con la esperanza de que la gente de todas formas resulta de los documentos .. :) – liaK

+0

qué parte de mi ejemplo esencialmente 3 línea no está claro? Por cierto, su ejemplo dará lugar a una falla de segmentación, porque el ptr de ámbito todavía DEBE la instancia, por eso utilicé .take(). – akira

3

Use QSharedPointer en su lugar.

QList<QSharedPointer<MyObject> > list; 

Para liberar memoria es suficiente con hacer

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

para añadir a la lista

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