24

新的 Qt5 信号和槽语法使我们不仅可以将信号连接到槽,还可以连接到普通的旧函数和仿函数/lambdas。现在的问题是,lambda 本质上是带有 () 运算符的对象,当您将信号连接到它们时,它们会被复制到 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 回答