2012-12-12 11 views
19

La nuova sintassi di segnali e slot Qt5 ci consente di collegare segnali non solo a slot, ma anche a semplici vecchie funzioni e funzioni/lambda. Ora il problema è che i lambdas sono essenzialmente oggetti con operatore(), e quando si collegano i segnali a loro, vengono copiati da qualche parte nelle classi interne di qt. E, quando disconnetti il ​​segnale da quel functor, rimane in qt internals. Non riesco a capire, è un comportamento normale? O forse c'è un modo per distruggere quegli oggetti funzionali dopo la disconnessione?Qt5 nuovo segnale per perdita di memoria connessioni lambda

Ecco un esempio:

//example 

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

    QTimer* timer = new QTimer(); 

    QSharedPointer<QMetaObject::Connection> connection(new QMetaObject::Connection()); 

    //functor is created and gets copied inside qt internals, connection variable is captured 
    //inside the functor 

    *connection.data() = QObject::connect(timer, &QTimer::timeout, [=] 
    { 
     qDebug() << "disconnected"; 
     QObject::disconnect(*connection.data()); 
    }); 

    timer->start(10000); 

    return a.exec(); 
} 

//example 

Ora, quando guardo forte conteggio di riferimento variabile connection dopo la fessura disconnessione, rimane 2, il che significa che l'oggetto funtore stesso è ancora viva e, sebbene non serve a me ora. Mi manca qualcosa?

+0

cosa succede quando si distruggono il timer? –

+0

Aveva anche questo pensiero, ma il conteggio dei riferimenti rimane 2 =/ – Sigil

+0

L'unico modo in cui va a 1 se non memorizzo la variabile di connessione in quella parte '* connection.data() =' ed elimina il timer. Che è ancora molto strano – Sigil

risposta

7

L'esempio è troppo ingegnerizzato (perché utilizzare QSharedPointer? Perché catturarlo in base al valore?). Ma in effetti Qt sta perdendo l'oggetto del funtore.

Il punto è che l'elenco delle connessioni interne viene semplicemente contrassegnato come sporco e non cancellato fino a quando il mittente non viene eliminato o non viene collegato un nuovo segnale (vedere gli usi di cleanConnectionLists).

ho spinto un paio di patch che dovrebbe risolvere questo comportamento: https://codereview.qt-project.org/#change,42976 e 42979

+1

Beh sì, so che potrebbe sembrare un po 'troppo ingegnerizzato, ma avevo bisogno di quel puntatore condiviso solo per essere in grado di monitorare facilmente il numero di riferimenti ad esso, per vedere se l'oggetto del funtore fosse ancora vivo, e io ho un progetto reale in cui la logica simile non è all'interno della funzione principale, quindi non posso semplicemente catturare la connessione per riferimento lì. – Sigil