QSharedPointer

Alles rund um die Programmierung mit Qt
Antworten
DBGTMaster
Beiträge: 190
Registriert: 19. August 2010 10:00

QSharedPointer

Beitrag von DBGTMaster »

Hallo,

folgender Code:

Code: Alles auswählen

typedef QSharedPointer<Database> DB;

...
...

DB t = DatabasePool::getConnection();
DB v = DatabasePool::getConnection();
Bei jedem Aufruf von getConnection wird ein QSharedPointer zurückgegeben, in diesem Fall zeigen beide QSharedPointer auf dem selben Pointer, wobei bei jedem getConnection aufruf ein eigenes QSharedObjekt erzeugt wird:

Code: Alles auswählen

DB DatabasePool::getConnection() {
    return QSharedPointer<DB>(ptr);
}
Problem ist nun, nach Ende der Methode wird versucht, der Pointer 2x zu zerstören, ich will diesen aber nur 1x zerstören...

Lösung wäre, ich gebe jedes mal das selbe QSharedPointer Objekt zurück... Aber hier wieder ist das Problem, wenn ich das QSharedObjekt in der Klasse "DatabasePool" zwischenspeichere, wird der Pointer nie zerstört, da eben die DatabasePool Klasse auch den QSharedPointer hält...

Was kann ich tun?

lG
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Re: QSharedPointer

Beitrag von franzf »

Code: Alles auswählen

return QSharedPointer<DB>(ptr);
Das kann nur schief gehen. Die Methode gibt jedes mal einen komplett unabhängigen shared_ptr zurück, so dass natürlich viele den Pointer töten wollen. SharedPoii´nter machen aber nur dann Sinn, wenn ALLE SharedPointer, die sich um den selben Zeiger kümmern, auch alle gemeinsam zählen.
Lösung:
* Entweder ptr direkt selber als QSharedPointer deklarieren
* komplett auf Smart-pointer verzichten, und jemandem die Verantwortung übertragen.

// sry, das am Ende hab ich nicht mehr geselen...
Wann soll denn deiner Meingung nach der Zeiger dann zerstört werden? Wenn kein Benutzer außerhalb mehr eine Referenz darauf hält?
DBGTMaster
Beiträge: 190
Registriert: 19. August 2010 10:00

Re: QSharedPointer

Beitrag von DBGTMaster »

franzf hat geschrieben:Wann soll denn deiner Meingung nach der Zeiger dann zerstört werden? Wenn kein Benutzer außerhalb mehr eine Referenz darauf hält?
Ganz genau das benötige ich... Und ich hätte gedacht, das tut QSharedPointer auch, aber leider nicht, wie ich festgestellt habe :(..

Gibts alternativen??

lG
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Re: QSharedPointer

Beitrag von Christian81 »

Abgesehen davon dass ich nicht glaube das es kompiliert - es sollte doch sicherlich 'return QSharedPointer<Database>(ptr)' heissen, oder?

Doch - es macht genau was Du sagst - erzeuge ein Objekt vom Typ QSharedPointer und gib es zurück und wenn der RefCount genau dieses Objektes 0 ist dann zerstöre das Objekt.
Du solltest ptr direkt als QSharedPointer<> ablegen.
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
DBGTMaster
Beiträge: 190
Registriert: 19. August 2010 10:00

Re: QSharedPointer

Beitrag von DBGTMaster »

Christian81 hat geschrieben:Du solltest ptr direkt als QSharedPointer<> ablegen.
Sorry, aber ich versteh nicht, was du mit dieser Aussage sagen willst???
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Re: QSharedPointer

Beitrag von Christian81 »

ptr ist doch (trotz der nicht vorhandenen Kennzeichnung per Notation oder ähnliches) hoffentlich ein Member von DatabasePool. Also mach dort nen QSharedPointer draus.
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
DBGTMaster
Beiträge: 190
Registriert: 19. August 2010 10:00

Re: QSharedPointer

Beitrag von DBGTMaster »

Christian81 hat geschrieben:ptr ist doch (trotz der nicht vorhandenen Kennzeichnung per Notation oder ähnliches) hoffentlich ein Member von DatabasePool. Also mach dort nen QSharedPointer draus.
Nein, das kann ich nicht tun. Die Klasse DatabasePool ist eine statische Klasse, und wenn ich dort als Member mein QSharedObjekt ablege, so lebt dieses auch so lange, wie das Programm läuft.

Wenn ich meinen QSharedPointer als member ablege, so muss ptr bereits zerstört werden, sobald noch ein SharedPointer auf ptr verweist, nämlich der, des QDatabasePool...

Aber ich denke, hier werde ich wohl einen eigenen SharedPointer schreiben müssen??

// Edit:
Wenn ich die Doku richtig verstanden habe, so kann ich im DatabasePool den Pointer als QWeakPointer ablegen, und daraus jedes mal bei der getConnection() Methode als QSharedPointer zurückgeben??
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Re: QSharedPointer

Beitrag von Christian81 »

Was willst Du überhaupt erreichen? Ich sehe keinen Grund warum hier ein QSharedPointer nötig wäre...
Und sag mir bitte nicht dass 'ptr' ein globaler statischer Pointer ist!
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
DBGTMaster
Beiträge: 190
Registriert: 19. August 2010 10:00

Re: QSharedPointer

Beitrag von DBGTMaster »

Christian81 hat geschrieben:Was willst Du überhaupt erreichen? Ich sehe keinen Grund warum hier ein QSharedPointer nötig wäre...
Und sag mir bitte nicht dass 'ptr' ein globaler statischer Pointer ist!
Doch, es ist ein globaler statischer Pointer :-) ....

Nein, Scherz bei Seite, ... Mir fehlt gerade die Zeit, das ganze etwas zu erklären...

Aber hier mein Lösungsweg, hier wird der Destruktor nur mehr 1x aufgerufen:

Code: Alles auswählen

class Test {
public:
    ~Test() {
        qDebug("destroy");
    }
};

void test() {

    QWeakPointer<Test> weak = QWeakPointer<Test>( QSharedPointer<Test>(new Test) );

    QSharedPointer<Test> a = weak.toStrongRef();
    QSharedPointer<Test> b = weak.toStrongRef();
    QSharedPointer<Test> c = weak.toStrongRef();
    QSharedPointer<Test> d = weak.toStrongRef();
}
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Re: QSharedPointer

Beitrag von franzf »

Ja, aber dein ptr wird DIREKT NACH der Erstellung des weak wieder zerstört (temporärer SharedPointer...).
Wenn du mir nicht glaubst:

Code: Alles auswählen

#include <QtCore/QDebug>
#include <QtCore/QSharedPointer>
#include <QtCore/QWeakPointer>


class Test {
public:
    ~Test() {
        qDebug("destroy");
    }
};

int main() {

    QWeakPointer<Test> weak = QWeakPointer<Test>( QSharedPointer<Test>(new Test) );
    qDebug() << "Vor toStrongRef";

    QSharedPointer<Test> a = weak.toStrongRef();
    QSharedPointer<Test> b = weak.toStrongRef();
    QSharedPointer<Test> c = weak.toStrongRef();
    QSharedPointer<Test> d = weak.toStrongRef();
    
    qDebug() << "Nach toStrongRef";
}
Du kannst auch a.isNull() oder weak.isNull() aufrufen - gibt immer true zurück.

Du wirst dir einen eigenen sharedptr schreiben dürfen, der bei genau einer Referenz schon zerstört (derjenigen statischen) und nicht erst bei count==0.
Antworten