c++ 在Qt5中断开lambda函数

2skhul33  于 2023-10-20  发布在  其他
关注(0)|答案(4)|浏览(131)

是否可以断开lambda函数?如果“是”,怎么做?
根据https://qt-project.org/wiki/New_Signal_Slot_Syntax,我需要使用一个从QObject::connect方法返回的QMetaObject::Connection,但是我如何将该对象传递给lambda函数呢?
伪代码示例:

QMetaObject::Connection conn = QObject::connect(m_sock, &QLocalSocket::readyRead, [this](){
    QObject::disconnect(conn); //<---- Won't work because conn isn't captured

    //do some stuff with sock, like sock->readAll();
}
q9rjltbz

q9rjltbz1#

如果你直接捕获conn,你是通过复制捕获一个未初始化的对象,这会导致未定义的行为。您需要捕获一个智能指针:

std::unique_ptr<QMetaObject::Connection> pconn{new QMetaObject::Connection};
QMetaObject::Connection &conn = *pconn;
conn = QObject::connect(m_sock, &QLocalSocket::readyRead, [this, pconn, &conn](){
    QObject::disconnect(conn);
    // ...
}

或者使用共享指针,开销稍大:

auto conn = std::make_shared<QMetaObject::Connection>();
*conn = QObject::connect(m_sock, &QLocalSocket::readyRead, [this, conn](){
    QObject::disconnect(*conn);
    // ...
}

从Qt 5.2开始,你可以使用一个context对象:

std::unique_ptr<QObject> context{new QObject};
QObject* pcontext = context.get();
QObject::connect(m_sock, &QLocalSocket::readyRead, pcontext,
    [this, context = std::move(context)]() mutable {
    context.reset();
        // ...
 });
50pmv0ei

50pmv0ei2#

ecatmur的答案中的上下文解决方案是最简单的选择,但我认为智能指针的使用使其难以理解。我更喜欢使用原始指针:

QObject *context = new QObject(this);
connect(sender, &Sender::signal, context, [context] {
  delete context;
  // ...
});
yquaqz18

yquaqz183#

Qt 6增加了Qt::SingleShotConnection连接类型。如果意图是在第一次呼叫后无条件地断开连接(而不是基于其他条件断开连接),那么这将起作用:

connect(sender, &Sender::signal, context, [] {
  // ...
}, Qt::SingleShotConnection);
9lowa7mx

9lowa7mx4#

您可以在.h文件中将conn定义为私有变量。QMetaObject::Connection conn
在lambda函数中,可以使用conn并断开连接。

conn = QObject::connect(m_sock, &QLocalSocket::readyRead, [=](){
    QObject::disconnect(conn); //<---- Won't work because conn isn't captured

    //do some stuff with sock, like sock->readAll();
}

相关问题