新的Qt5信号和插槽语法使我们不仅可以将信号连接到插槽,还可以连接普通旧功能和仿函数/ lambda。现在的问题是,lambdas是带有()运算符的必要对象,当你将信号连接到它们时,它们会被复制到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,这意味着仿函数对象本身仍然存活且很好,尽管现在对我没用。我想念一下吗?
答案 0 :(得分:8)
该示例过度设计(为什么使用QSharedPointer?为什么要按值捕获它?)。但实际上Qt正在泄漏仿函数对象。
重点是内部连接列表只是标记为脏,并且在删除发件人或连接新信号之前不会清除(请参阅cleanConnectionLists的用法)。
我推了几个应该修复此行为的补丁:https://codereview.qt-project.org/#change,42976和42979