24

新しいQt5シグナルとスロットの構文により、シグナルをスロットだけでなく、プレーンな古い関数やファンクター/ラムダにも接続できます。ここで問題となるのは、ラムダは本質的に()演算子を持つオブジェクトであり、シグナルをそれらに接続すると、それらはqt内部クラスのどこかにコピーされるということです。そして、そのファンクターからシグナルを切断すると、qt内部にとどまります。私は理解できません、それは正常な行動ですか?または、切断後にこれらの機能オブジェクトを破棄する方法はありますか?

次に例を示します。

//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

スロットを切断した後の接続変数の強い参照カウントを見ると、2のままです。これは、ファンクターオブジェクト自体がまだ健在であることを意味しますが、今は役に立たないのです。私は何かが恋しいですか?

4

1 に答える 1

10

この例は過剰に設計されています(QSharedPointerを使用する理由、値でキャプチャする理由)。しかし実際、Qtはファンクターオブジェクトをリークしています。

重要なのは、内部接続リストは単にダーティとしてマークされ、送信者が削除されるか、新しいシグナルが接続されるまでクリアされないということです(cleanConnectionListsの使用法を参照)。

この動作を修正するパッチをいくつかプッシュしました:https : //codereview.qt-project.org/#change,42976および42979

于 2012-12-16T23:59:40.857 に答える