2009-04-25 16 views
5

¿Qué opinas? ¿Es correcto o hay pérdidas de memoria?QList y shared_ptr

Fuente:

#include <QList.h> 
#include <boost/shared_ptr.hpp> 
#include <iostream> 

class A { 
private: 
    int m_data; 
public: 
    A(int value=0) { m_data = value; } 
    ~A() { std::cout << "destroying A(" << m_data << ")" << std::endl; } 
    operator int() const { return m_data; } 
}; 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    QList<boost::shared_ptr<A> > list; 
    list.append(boost::shared_ptr<A>(new A(6))); 
    std::cout << int(*(list.at(0))) << std::endl; 
    return 0; 
} 

Salida:

6 
destroying A(6) 
+2

Como nota al margen: no utilizar '' QList donde 'sizeof (T)> sizeof (void *)' (y 'sizeof (shared_ptr ) == 2 * sizof (void *)', por lo general), ya que en ese caso 'QList' copiará -'nuevo' los elementos en la lista (en lugar de mantenerlo por valor). Use 'QVector' o' std :: vector' en su lugar. –

Respuesta

1

Parece correcto. El shared_ptr de Boost es un puntero de conteo de referencia. El recuento de referencias puede reclamar memoria si no hay referencias circulares entre objetos. En su caso, los objetos de la clase A no hacen referencia a ningún otro objeto. Por lo tanto, puedes usar shared_ptr sin preocupaciones. Además, la semántica de propiedad permite que shared_ptrs se use en contenedores STL (y Qt).

1

Es difícil sugerir algo sin saber por qué la lista de shared_ptr s de A objetos existe en el primer lugar.

Eche un vistazo a ownership semantics de punteros inteligentes. Quizás de ayuda para ti.

Algunas otras cosas que se pueden mejorar:

1. listas Uso de inicializador en ctor como:

class A { 
private: 
    int m_data; 
public: 
    A(int value=0) : m_data (value) {} 
// .... 

2.int _tmain(int argc, _TCHAR* argv[]) no es una firma estándar;

Uso

int main(int argc, char* argv[]) 

o simplemente:

int main() 
+0

No estoy seguro de lo que quiere decir con su primer punto. ¿Dónde debería usar las listas de inicializadores? '_tmain' era el valor predeterminado cuando se usaba el asistente de Visual Studio, ¡pero gracias por esa pista! – WolfgangA

+1

_tmain (int argc, _TCHAR * argv []) es una firma válida en VC++ :). Es un método principal que toma argumentos multibyte o unicode, dependiendo de un cambio en VS. También hay un int wmain (int argc, wchar_t * argv []). – Skurmedel

+0

Una implementación puede proporcionar N firmas diferentes de main. El lenguaje estándar define solo dos (mencioné arriba). – dirkgently

1

Este código se ve perfectamente bien.

Si está buscando asesoramiento, tal vez podría proporcionar más información sobre el propósito de utilizar shared_ptr con QList, podría haber una forma de "Qt" de hacer esto sin tirar de las grandes armas como shared_ptr.

+1

eso no es del todo correcto. podría usar el árbol de propiedad de objetos de Qt como el diseño, pasando el QList como el propietario de cada objeto insertado en él. es una técnica muy útil cuando se trabaja con Qt. Lea más sobre esto aquí: http://doc.trolltech.com/4.5/objecttrees.html –

+0

@daniel Esa no es una opción aquí, ya que los padres y los niños tienen que ser subclases de QObject para que funcionen. QList no es un QObject, por lo que es un no ir incluso si A hereda de QObject. –

1

Si no está utilizando un puntero inteligente, debe eliminar los elementos de la lista usted mismo.

Fuente:

#include <QList.h> 
#include <boost/shared_ptr.hpp> 
#include <iostream> 

class A { 
private: 
    int m_data; 
public: 
    A(int value=0) { m_data = value; } 
    ~A() { std::cout << "destroying A(" << m_data << ")" << std::endl; } 
    operator int() const { return m_data; } 
}; 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    QList<A *> list; 
    list.append(new A(6)); 
    std::cout << int(*(list.at(0))) << std::endl; 
    return 0; 
} 

Salida:

6 

No es bueno.

+0

Luego simplemente elimine el operador "nuevo" y los objetos A serán deconstruidos cuando esté el QList. –