2009-04-25 10 views
5

Co myślisz? Czy to prawda, czy są wycieki pamięci?QList i shared_ptr

Źródło:

#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; 
} 

wyjściowa:

6 
destroying A(6) 
+2

Jako zdaniu: nie używaj 'QList ' gdzie 'sizeof (T)> sizeof (void *)' (i 'sizeof (shared_ptr ) == 2 * sizof (void *)', zwykle), skoro w tym przypadku 'QList' skopiuje' 'new' elementy do listy (w przeciwieństwie do trzymania jej przez wartość). Zamiast tego użyj 'QVector' lub' std :: vector'. –

Odpowiedz

1

Wygląda na to, że jest poprawny. Boost's shared_ptr jest referencyjnym wskaźnikiem zliczającym. Licznik odwołań jest w stanie odzyskać pamięć, jeśli nie ma żadnych odwołań kołowych między obiektami. W twoim przypadku obiekty klasy A nie odwołują się do żadnych innych obiektów. W ten sposób możesz używać shared_ptr bez obaw. Ponadto semantyka własności zezwala na używanie shared_ptrs w kontenerach STL (i Qt).

1

Trudno sugerować niczego nie wiedząc dlaczego lista shared_ptr s od A obiekty istnieją w pierwszej kolejności.

Spójrz na ownership semantics inteligentnych wskaźników. Może ci pomóc.

Kilka innych rzeczy, które można poprawić:

1. list Wykorzystanie initializer w ctor jak:

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

2.int _tmain(int argc, _TCHAR* argv[]) podpis nie jest standardowa;

Zastosowanie

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

lub po prostu:

int main() 
+0

Nie jestem pewien, co masz na myśli mówiąc o swoim pierwszym punkcie. Gdzie powinienem używać list inicjalizujących? '_tmain' był domyślny przy użyciu kreatora Visual Studio, ale dziękuję za podpowiedź! – WolfgangA

+1

_tmain (int argc, _TCHAR * argv []) jest prawidłowym podpisem na VC++ :). Jest to główna metoda pobierająca argumenty wielobajtowe lub Unicode, w zależności od przełącznika w VS. Istnieje również int wmain (int argc, wchar_t * argv []). – Skurmedel

+0

Implementacja może dostarczyć N różnych podpisów głównych. Standard językowy definiuje tylko dwa (wymienione powyżej). – dirkgently

1

Ten kod wygląda perfekcyjnie.

Jeśli chcesz uzyskać poradę, możesz podać więcej informacji na temat używania shared_ptr z QList, może to być metoda "Qt" bez ciągnięcia dużych broni, takich jak shared_ptr.

+1

To nie do końca poprawne. możesz użyć drzewa własności obiektu Qt, takiego jak layout, przekazując QList jako właściciela każdego wstawionego do niego obiektu. to bardzo przydatna technika podczas pracy z Qt. przeczytaj więcej na ten temat tutaj: http://doc.trolltech.com/4.5/objecttrees.html –

+0

@daniel To nie jest opcja tutaj, ponieważ rodzice i dzieci muszą być podklasami QObject, aby to działało. QList nie jest QObject, więc nie da się go przejść, nawet jeśli A odziedziczył po QObject. –

1

Jeśli nie używasz inteligentnego wskaźnika, musisz sam usunąć elementy listy.

Źródło:

#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; 
} 

wyjściowa:

6 

nie jest dobra.

+0

Następnie wystarczy usunąć "nowego" operatora, a obiekty A zostaną zdekonstruowane, gdy jest QList. –