这两个 qt 信号槽连接之间的功能区别是什么?

What is the functional difference between these two qt signal-slot connections?

我正在使用带有 Visual Studio 2015 的 Qt 5.9.2 和 QtDesigner 来编写 Windows GUI 应用程序。我尝试通过以下调用连接我的一项操作:

connect(ui.myAction, &QAction::triggered, memberPtrToObjX_, &ClassX::Run);

但是 ClassX::Run 并不总是在单击菜单栏中的 myAction 后触发。调查这个问题,我想,使用 lambda 语法的相同信号槽连接有效:

connect(ui.myAction, &QAction::triggered, [this](bool run) { memberPtrToObjX_->Run(run); });

我很确定,这两个调用在语法上都是正确的。除了两个调用 return 一个有效的 QMetaObject::Connection,如果我保存 return 值并使用 operator bool() 检查。

显然我可以坚持使用工作 lambda 版本,但我很困惑并且更愿意知道我 "solution" 背后的原因。这两个调用之间是否存在任何功能差异,可以解释不同的行为?

QObject::connect() 的两个调用(由 OP 公开)在 this->memberPtrToObjX_connect().

调用之后修改的情况下表现不同

第一个

connect(ui.myAction, &QAction::triggered, memberPtrToObjX_, &ClassX::Run);

来电
QMetaObject::Connection QObject::connect(<br/> const QObject *sender, PointerToMemberFunction signal,<br/> const QObject *receiver, PointerToMemberFunction method,<br/> Qt::ConnectionType type = Qt::AutoConnection).

Creates a connection of the given type from the signal in the sender object to the method in the receiver object. Returns a handle to the connection that can be used to disconnect it later.

因此,this->memberPtrToObjX_中的当前指针连接为信号接收器。如果在connect()之后修改了this->memberPtrToObjX_,这对信号连接没有任何影响。

第二个

connect(ui.myAction, &QAction::triggered, [this](bool run) { memberPtrToObjX_->Run(run); });

来电
QMetaObject::Connection QObject::connect(<br/> const QObject *sender, PointerToMemberFunction signal,<br/> Functor functor).

Creates a connection from signal in sender object to functor, and returns a handle to the connection.

因此,lambda(后面的函子)作为接收者连接。 lambda 在执行时解析 this->memberPtrToObjX_ 中的指针,即触发信号时。


第二个区别(最初在G.M的评论中发现)是连接类型:

第一个版本使用默认值 Qt::AutoConnection(因为它没有明确定义)。带有 lambda 的版本总是使用 Qt::DirectConnection

如果 this->memberPtrToObjX_ 中的指针不在同一线程中 "live",就会出现差异。在这种情况下,Qt::AutoConnection 被解析为 Qt::QueuedConnection 而不是 Qt::DirectConnection

我假设 this->memberPtrToObjX_ 中的指针会在同一个 QThread 中 "live"。如果不是,第二个版本(带有 lambda)变得非常有问题,因为它在不同的线程中调用对象 "living" 的成员函数(此时很难判断该线程在做什么)。这只是 似乎 效果更好,但很可能是 "time bomb".