【发布时间】:2017-08-11 21:59:23
【问题描述】:
我需要帮助了解 lambda 函数的工作方式,以防止在使用它们时发生内存泄漏。更具体地说,我想知道foo在以下情况下何时被销毁:
void MainWindow::onButtonClicked()
{
QTimer *t(new QTimer(this));
bool foo = false;
t->setSingleShot(true);
t->setInterval(1000);
t->start();
connect(t, &QTimer::timeout, [=](){
delete t;
qDebug() << foo;
});
}
使用[&]的情况如何?
【问题讨论】:
-
正如所写,
t是按值捕获的,lambda 存储指针的副本。没关系。如果改为通过引用捕获,则一旦函数返回,lambda 将以悬空引用结束,并且一旦调用该 lambda,程序就会表现出未定义的行为。 -
@IgorTandetnik,foo 呢?
-
同样的事情 - 如果按值捕获则很好,如果按引用捕获则悬空引用。
-
一个lambda只是编译器自动生成的某个类的一个对象;
foo成为该类的数据成员。粗略地说,你最终会得到class L { QTimer *t; bool foo; void operator()(); };。 lambda 表达式创建该类的一个实例——它是一个临时的,它将在分号处被销毁(当然,连同它的成员变量一起)。connect抓取一个临时副本,并将其存放在某个地方。当QTimer对象被销毁,或者当您通过disconnect()断开连接时,它将被销毁 -
事实上,现在我想起来了,您的程序可能会通过在对象的生命周期结束后访问对象而表现出未定义的行为。
delete t;可能导致正在执行的 lambda 对象的破坏;此时,它的foo数据成员也将被销毁。之后使用是一个问题。您可能想使用QObject::deleteLater- 它就是为这种情况而发明的。