[Interest] Signal/Slot connection fails, even though QMetaObject::activate is called

Tony Rietwyk tony at rightsoft.com.au
Sat Feb 15 05:19:06 CET 2020


On 15/02/2020 7:01 am, Matthew Woehlke wrote:
> On 07/02/2020 19.10, Tony Rietwyk wrote:
>> Does it work if you don't pass 'this' as the third argument to connect?
>> I never use that particular overload of connect. I usually pass the
>> lambda as the third argument.
> That scares me. The third argument is the context in which the slot
> runs, i.e. the "receiver". If your lambda contains any state, not
> passing a context risks the slot being called after whatever owns that
> state has ceased to exist, which will likely lead to UB. (It also risks
> the lambda running in the wrong thread.)
>
> Basically, if your lambda has *any state at all*, you should *always*
> pass a context. The context should be a QObject which owns that state
> and whose thread can safely use the state.
>
> The context should only be omitted if your lambda is stateless, and even
> then I'd avoid doing so unless you really need to, or are making a
> deliberate choice that no one should "own" the connection.

That's strange - I thought the whole point of the [=] in the lambda is 
to capture a shallow copy of the state required by the code within the 
lambda.  Whereas [&] copies references to the state variables.  Of 
course, whether these copies or references work in whatever thread when 
the code is actually executed is up to you to guarantee - via 
QSharedPointers or whatever.  I haven't used lambdas across threads - in 
those cases I've used the receiver/pointer-to-method overload.

The third parameter context solely determines which thread's event loop 
the lambda runs in.  In the shorter overload, I would assume that the 
context is simply the current thread object.  Both overloads have the 
following warning:

     "The connection will automatically disconnect if the sender or the 
context is destroyed. However, you should take care that any objects 
used within the functor are still alive when the signal is emitted."

In my experience, coding in particular ways "because it scares you" 
often leads to poor results.  A C++ lambda is basically a temporary 
object with the copied or referenced state, and a call operator()(...) { 
/* lambda code */ }.

Regards, Tony




More information about the Interest mailing list