Congratulations to our 2022 Qt Champions!

QSharedPointer::data() as SIGNAL/SLOT parameter

  • I want to create a QSharedPointer in one class and submit the data as a SIGNAL parameter:

    @emit mySignal(<QSharedPointer<MyClass>(new MyClass).data());@

    Then I have a number of SLOTS connected to this SIGNAL. However, when I try to access the underlying data from the SLOT, it seems that the data was deleted.

    So my question is: will QSharedPointer keep reference count if I emit the underlying data, or do I have to emit the QSharedPointer as is (see example below)?

    @emit mySignal(<QSharedPointer<MyClass>(new MyClass));@

  • In your first emit you are just sending a pointer to the data the shared pointer is referencing. The shared pointer has no way to count the references to this. When the data will be released will be dependent on the way of your connect. In a syncronous connect, it will probably work.

    You have to use the second version of your emit.

    BTW: you have an extra '<' left of your QSharedPointer.

  • As soon as you touch the raw data, you're on your own in terms for ref counting. data() is a way to pass your class pointer to methods that require a raw pointer, but it is up to you to determine if that is safe for your case. In general, it breaks the concept of having a shared pointer at all. For example, using data() for QObject::connect() would be save, but normally methods that will store the pointer you pass in will not be save. If the method will "take ownership", it is definately unsafe to pass in a raw pointer via data().

    In your case, I would pass around the shared pointer via your signal if you need that. Why create a temporary shared pointer and then take the data member out of it again? It will just make sure that the instance is deleted as soon as the emit call finishes and the temporary goes out of scope. Would it not be possible to create a real value class that can safely be copied and does not need to be on the heap? It seems that that is what you are trying to achieve anyway: signal something that will be safely deleted if noone is interested in the signal value, right?

  • Thank you! I'll do that.

  • Yes, I've just created a "short version" of what I actually want to do (otherwise the post will be cluttered). So I will actually create it on the stack.

  • Well, if you create the value to emit on the stack, you certainly don't want to pass around a shared pointer to it. What happens if code receiving the signal stores the shared pointer for later access, and then the original stack value goes out of scope? You'll have a dangling pointer inside your shared pointer!

    Shared pointers basically give value semantics to heap object pointers. If you already have a value object, there is no need to add such a wrapper (and in fact, as demonstrated above, it is dangerous to do so).

  • Thanks Andre. Got a bit confused.

Log in to reply