QVector & Klassen mit dynamischen angelegten Variablen

Alles rund um die Programmierung mit Qt
Antworten
Razoron
Beiträge: 19
Registriert: 12. Dezember 2010 18:14

QVector & Klassen mit dynamischen angelegten Variablen

Beitrag von Razoron »

Hi,
die klasse Test hat eine dynamisch angeleten int, der im Destruktor automatisch deleted wird. Aleine klappt alles ohne Probleme. Aber sobald ich die Klasse in einen QVector speichere, bekomm ich beim clearen ein abort kassiert.
Woran kann das liegen?

Code: Alles auswählen

#include <QApplication>
#include <QVector>

class Test
{
private:
    int *i;

public:
    Test()
    {
        i = new int;
    }

    ~Test()
    {
        delete i;
    }
};

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    QVector<Test> vec;
    Test t;
    vec.push_back(t);
    vec.clear();

    return app.exec();
}
RHBaum
Beiträge: 1436
Registriert: 17. Juni 2005 09:58

Beitrag von RHBaum »

Du implementierst fuer Test einen Standard Ctor, aber keinen CCTor.
C++ generiert dir einen, der aber das Falsche macht(er kopiert einfach alle member), wenn du dynamsich zeugs da allokiert.

Damit erzeugst du folgendes verhalten:
du erzeugst t mittels SCTOR -> t.i wird mit new angelegt
du hausst t in den Vector, t wird mittels CCTOR kopiert, tx im Vector, tx.i zeigt auf t.i
t wird aufgeraeumt, t.i wird durch DTOR deleted
tx.i zeigt auf geloeschten speicher.
dein Vector wird demontiert
alle elemente vom vector werden vorher auch demontiert.
DTor von tx wird aufgerufen -> delete auf tx.i was ins nirvana zeigt -> schutzverletzung

teste mal mit:

Code: Alles auswählen

class Test
{
private:
    int *i;
    Test(const Test & rx); /// CCTOR verhindern. 
public:
    Test()
    {
        i = new int;
    }

    ~Test()
    {
        delete i;
    }
}; 
und schwupps, funktioniert deine Klasse nimmer im Container. Ergo Container nutzt CCTOR

CCTor implementieren :

Code: Alles auswählen

class Test
{
private:
    int *i;
    
public:
    Test()
    {
        i = new int;
    }
    Test(const Test & rx)
    {
         i = new int(*rx.i);
    }
    ~Test()
    {
        delete i;
    }
}; 

Deine Klassen hat noch ne paar Mängel, die in deinem Fall easy zu beheben sind:
- Initialisierungslisten verwenden wo geht !
- Rohe Zeiger meiden !
- Exceptionsicherheit und Speichermanagment !

Bessere Implementierung(wenn i denn unbedingt aufn freestore muss):


Code: Alles auswählen

#include <memory>

class Test
{
public:
    Test():
    mpIntVar(new int(0)) /// uninitialisierte Variablen sind doof, beleg sie mit 0
    {
    }
    Test(const Test & rx):
    mpIntVar(new int(*rx.mpIntvar.get()))
    {
    }
    ~Test() /// das delete geht durch den autoptr allein 
    {
    }
private:
   const std::auto_ptr<int> mpIntVar;
}; 
Ciao ....
Razoron
Beiträge: 19
Registriert: 12. Dezember 2010 18:14

Beitrag von Razoron »

Jo, danke, das war zwar nur eine Testklasse, aber ich werde wohl meine Klassen ausrüsten müssen :). Ich nehme mal an dafür gibts die Klasse QPointer (The Qt Way)?
RHBaum
Beiträge: 1436
Registriert: 17. Juni 2005 09:58

Beitrag von RHBaum »

Ja, smartpointer Impls gibts viele ... aber QPointer geht nur fuer QObjects also ned fuer ints ....

es gibt nen QSharedPointer, der macht referenzzaehlung, das funzt dann wieder anders.

Weiss ned ob Qt einen mit Besitzsemantic hat, der fuer diesen fall ideal ist ...

Aber die stl kannst schon verwenden
beim neuen standard (tr1 ehemals) kommt da mehr hinzu ...
boost iss auch ne alternative.

Ciao ...
Razoron
Beiträge: 19
Registriert: 12. Dezember 2010 18:14

Beitrag von Razoron »

Gut, danke :).
Antworten