Page 1 of 2 12 LastLast
Results 1 to 20 of 21

Thread: QSharedPointer with signals and slots

  1. #1
    Join Date
    Aug 2010
    Posts
    99
    Thanks
    3
    Qt products
    Qt4
    Platforms
    Windows

    Default QSharedPointer with signals and slots

    I have recently started using QSharedPointer for a particular type of object which is shared between many classes. Previously i had just used a raw pointer and managed the creation and deletion of the objects in one place. But now i realise it will be much easier (and actually necessary) to do reference counting.

    For some reason, there are very few examples out there on how to use QSharedPointer, so i find myself posting here.

    One problem i have ran into is using signals and slots with the objects that are shared-pointed-to. Previously i had done this:
    Qt Code:
    1. MyObject* object; // Subclass of QObject.
    2. AnotherObject* something;
    3. ...
    4. connect(object, SIGNAL(updated()), something, SLOT(update())); // Notify when my object has changed
    To copy to clipboard, switch view to plain text mode 

    But now that i have changed MyObject* to QSharedObject<MyObject> (typedef'd as MyObjectPtr), the compiler complains:
    error C2664: 'bool QObject::connect(const QObject *,const char *,const QObject *,const char *,Qt::ConnectionType)' : cannot convert parameter 1 from 'MyObjectPtr' to 'const QObject *'
    No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
    I read that i need to use Q_DECLARE_METATYPE and qRegisterMetaType, but i'm not sure about that.
    QObject::connect takes a pointer, but here i am passing a QSharedPointer object. Would doing the above allow that type to be passed? Do i still need to do that if the MyObject class is already a subclass of QObject?
    And is it safe to just pass the raw pointer obtained from object.data()?
    [Window Detective] - Windows UI spy utility
    [War Thunder]

  2. #2
    Join Date
    Sep 2011
    Posts
    1,245
    Thanks
    3
    Thanked 127 Times in 126 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: QSharedPointer with signals and slots

    But now that i have changed MyObject* to QSharedObject<MyObject> (typedef'd as MyObjectPtr), the compiler complains:
    whats a QSharedObject ?


    Added after 4 minutes:


    And is it safe to just pass the raw pointer obtained from object.data()?
    Why wouldn't it be?
    Last edited by amleto; 25th June 2012 at 09:21.
    If you have a problem, CUT and PASTE your code. Do not retype or simplify it. Give a COMPLETE and COMPILABLE example of your problem. Otherwise we are all guessing the problem from a fabrication where relevant details are often missing.

  3. #3
    Join Date
    Aug 2010
    Posts
    99
    Thanks
    3
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: QSharedPointer with signals and slots

    Quote Originally Posted by amleto
    whats a QSharedObject ?
    Oops, i mean't QSharedPointer. I guess i didn't proof-read my post good enough.

    And is it safe to just pass the raw pointer obtained from object.data()?
    Why wouldn't it be?
    I don't know, that's why i'm asking . I know not to go passing the QSharedPointer's internal raw pointer around, because then it cannot do reference counting properly. But i'm not sure how signals and slots handle it. That is, i don't know if Qt would internally hold onto the pointer somewhere.
    Then again, since all signals to and from the object are disconnected when it is destroyed, i guess there is no chance of a dangling pointer. I just wanted to make sure i was doing it the right way.


    EDIT1:
    Another problem i just ran into is using shared pointers as keys in a QMap.
    For example: QMap<MyObjectPtr, AnotherObject*>

    These objects that i am referring to (the one's i call "MyObject") are stored in a list, which is managed by one class. Previously, if any other classes wanted to use those objects, they would keep a pointer to them. No-one but the manager class would delete the objects. So i could do things like use the pointers as a key in a map, because the pointer would always point to the same object.

    Now, i would be storing a QSharedPointer object as the key, which is obviously not going to be the same QSharedPointer object that other classes have.


    EDIT2:
    Actually, i think QSharedData and QSharedDataPointer are probably what i want. Then i can use MyObject in the same manner as the implicitly shared Qt classes like QString. Although i'm still not sure if or how i can use these objects as keys in a QMap or QHash, or connect them to signals.
    Last edited by xtal256; 26th June 2012 at 02:49.

  4. #4
    Join Date
    Sep 2011
    Posts
    1,245
    Thanks
    3
    Thanked 127 Times in 126 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: QSharedPointer with signals and slots

    "Now, i would be storing a QSharedPointer object as the key, which is obviously not going to be the same QSharedPointer object that other classes have."

    Not sure why that is a problem. It shouldn't be. There is no problem using them as keys in maps etc. Your pointers that you were using before - you weren't using the same instance of a pointer to an object across all your classes (you had multiple instances of pointers to a specific instance), so why is the same situation for shared pointer going to be a problem?

    shared pointers and qshareddata(pointer) are fundamentally different so they aren't interchangeable (in the general case).
    Last edited by amleto; 26th June 2012 at 09:30.
    If you have a problem, CUT and PASTE your code. Do not retype or simplify it. Give a COMPLETE and COMPILABLE example of your problem. Otherwise we are all guessing the problem from a fabrication where relevant details are often missing.

  5. #5
    Join Date
    Aug 2010
    Posts
    99
    Thanks
    3
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: QSharedPointer with signals and slots

    Quote Originally Posted by amleto
    "Now, i would be storing a QSharedPointer object as the key, which is obviously not going to be the same QSharedPointer object that other classes have."

    Not sure why that is a problem. It shouldn't be. There is no problem using them as keys in maps etc. Your pointers that you were using before - you weren't using the same instance of a pointer to an object across all your classes (you had multiple instances of pointers to a specific instance), so why is the same situation for shared pointer going to be a problem?
    Yes, but the difference is that pointers are essentially just integers, and can be compared for equality. Objects cannot, unless they override the "==" operator. Ok, i see that QSharedPointer does indeed do that, so two different QSharedPointer objects that point to the same object will say they are equal. But they do not implement the '<' operator, so i get the following compile error when using a QMap:

    error C2678: binary '<' : no operator found which takes a left-hand operand of type 'const MyObjectPtr' (or there is no acceptable conversion)

    Should i perhaps use a QHash instead?


    EDIT: I just found out (from this post) that in order for QSharedPointer to work properly, i must only copy an existing shared pointer and not create new ones from the same raw pointer.
    So in some cases, where i have code like this:
    Qt Code:
    1. class MyObject {
    2. ...
    3. void doSomething() {
    4. anotherObject->doSomethingWith(this);
    5. }
    6. }
    To copy to clipboard, switch view to plain text mode 
    I cannot simply wrap a QSharedPointer (i.e. MyObjectPtr typedef) around "this". If i do that, then "anotherObject" will get a shared pointer with it's own reference count, which will be different to that of the shared pointer that other classes may have.
    Last edited by xtal256; 27th June 2012 at 04:55.
    [Window Detective] - Windows UI spy utility
    [War Thunder]

  6. #6
    Join Date
    Sep 2011
    Posts
    1,245
    Thanks
    3
    Thanked 127 Times in 126 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: QSharedPointer with signals and slots

    Yes, qhash should work in this case (operator== is present).

    Does anotherObject really need the shared pointer, or just a weak one? Otherwise I would consider looking at boost shared_from_this
    If you have a problem, CUT and PASTE your code. Do not retype or simplify it. Give a COMPLETE and COMPILABLE example of your problem. Otherwise we are all guessing the problem from a fabrication where relevant details are often missing.

  7. #7
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,364
    Thanks
    3
    Thanked 5,013 Times in 4,791 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: QSharedPointer with signals and slots

    Quote Originally Posted by xtal256 View Post
    I cannot simply wrap a QSharedPointer (i.e. MyObjectPtr typedef) around "this". If i do that, then "anotherObject" will get a shared pointer with it's own reference count, which will be different to that of the shared pointer that other classes may have.
    I think you misunderstood that post. In the situation you describe you will get 'the same' shared pointer.

    This is valid and correct:
    Qt Code:
    1. int *i = new int(6);
    2. QSharedPointer<int> a(i);
    3. QSharedPointer<int> b = a;
    To copy to clipboard, switch view to plain text mode 

    This is not:
    Qt Code:
    1. int *i = new int(6);
    2. QSharedPointer<int> a(i);
    3. QSharedPointer<int> b(i);
    To copy to clipboard, switch view to plain text mode 

    If doSomethingWith() accepts a shared or a weak pointer, you are fine.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  8. #8
    Join Date
    Aug 2010
    Posts
    99
    Thanks
    3
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: QSharedPointer with signals and slots

    Actually, i understood the post exactly as you described it. If MyObject::doSomething is called twice, it will be like the "wrong" code you just posted, because a new QSharedPointer will be created each time it's called.

    And i'm not sure a weak pointer is right for this occasion.
    Basically, i need to pass an instance of MyObject to another object for it to use. So it's more like this:

    Qt Code:
    1. class MyObject {
    2. ...
    3. AnotherObject* makeAnotherObject() {
    4. return new AnotherObject(this);
    5. }
    6. }
    7.  
    8. class AnotherObject {
    9. MyObject* blah;
    10. AnotherObject(MyObject* o) : blah(o) {}
    11. ...
    12. }
    13.  
    14. MyObject* foo = getObject(); // Could be a subclass
    15. AnotherObject* bar = foo->makeAnotherObject();
    To copy to clipboard, switch view to plain text mode 

    Then foo could be deleted at some point while bar still exists (and still wants to use foo). So how do i handle this situation using shared pointers? Keep in mind that the foo instance does not solely belong to bar, so other things will have a reference to it.
    Last edited by xtal256; 28th June 2012 at 07:57.

  9. #9
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,364
    Thanks
    3
    Thanked 5,013 Times in 4,791 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: QSharedPointer with signals and slots

    Quote Originally Posted by xtal256 View Post
    If MyObject::doSomething is called twice, it will be like the "wrong" code you just posted, because a new QSharedPointer will be created each time it's called.
    If you make the method accept a shared pointer instead of a regular pointer then no, it will not be the wrong code.

    Basically, i need to pass an instance of MyObject to another object for it to use. So it's more like this:

    Qt Code:
    1. class MyObject {
    2. ...
    3. AnotherObject* makeAnotherObject() {
    4. return new AnotherObject(this);
    5. }
    6. }
    7.  
    8. class AnotherObject {
    9. MyObject* blah;
    10. AnotherObject(MyObject* o) : blah(o) {}
    11. ...
    12. }
    13.  
    14. MyObject* foo = getObject(); // Could be a subclass
    15. AnotherObject* bar = foo->makeAnotherObject();
    To copy to clipboard, switch view to plain text mode 
    Convert all "MyObject*" to "QSharedPointer<MyObject>" in the code above (and everywhere else you are using this object) and you'll be fine. Otherwise if you have a place somewhere that keeps the bare pointer, you can't use shared pointers at all anywhere.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  10. #10
    Join Date
    Sep 2011
    Posts
    1,245
    Thanks
    3
    Thanked 127 Times in 126 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: QSharedPointer with signals and slots

    Quote Originally Posted by wysota View Post
    If you make the method accept a shared pointer instead of a regular pointer then no, it will not be the wrong code.
    yes it will, because he will make a new shared pointer from 'this' every time he calls the method from that class. There are other classes that already have shared pointer to 'this', and their reference counts wont reflect this extra share.
    Last edited by amleto; 28th June 2012 at 09:58.
    If you have a problem, CUT and PASTE your code. Do not retype or simplify it. Give a COMPLETE and COMPILABLE example of your problem. Otherwise we are all guessing the problem from a fabrication where relevant details are often missing.

  11. #11
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,364
    Thanks
    3
    Thanked 5,013 Times in 4,791 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: QSharedPointer with signals and slots

    Where exactly does this happen in the below code?

    Qt Code:
    1. class MyObject {
    2. ...
    3. QSharedPointer<AnotherObject> makeAnotherObject() {
    4. return QSharedPointer<AnotherObject>(new AnotherObject(this)); // here? So have a map of instances of MyObject wrapped in QWeakPointer and pass that instead of "this"
    5. }
    6. }
    7.  
    8. class AnotherObject {
    9. QSharedPointer<MyObject> blah;
    10. AnotherObject(QSharedPointer<MyObject> o) : blah(o) {}
    11. ...
    12. }
    13.  
    14. QSharedPointer<MyObject> foo = getObject();
    15. QSharedPointer<AnotherObject> bar = foo->makeAnotherObject();
    To copy to clipboard, switch view to plain text mode 
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  12. #12
    Join Date
    Sep 2011
    Posts
    1,245
    Thanks
    3
    Thanked 127 Times in 126 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: QSharedPointer with signals and slots

    Using a weak reference doesn't guarantee the thing is alive when anotherobject wants to use it. If anotherobject only makes sense to be in existence with a live reference to myobject then we're not in a good place.

    It seems like the code could do with a bit of a design change tbh - responsibility/encapsulation feels a bit smeared.
    Last edited by amleto; 28th June 2012 at 10:48.
    If you have a problem, CUT and PASTE your code. Do not retype or simplify it. Give a COMPLETE and COMPILABLE example of your problem. Otherwise we are all guessing the problem from a fabrication where relevant details are often missing.

  13. #13
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,364
    Thanks
    3
    Thanked 5,013 Times in 4,791 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: QSharedPointer with signals and slots

    To be honest I fail to see the point of using shared pointers here at all.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  14. #14
    Join Date
    Sep 2011
    Posts
    1,245
    Thanks
    3
    Thanked 127 Times in 126 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: QSharedPointer with signals and slots

    I'm inclined to agree. If the op had all new/delete in a single place and its lifetime is guaranteed to be longer than the objects containing the pointers, then what is the problem?
    If you have a problem, CUT and PASTE your code. Do not retype or simplify it. Give a COMPLETE and COMPILABLE example of your problem. Otherwise we are all guessing the problem from a fabrication where relevant details are often missing.

  15. #15
    Join Date
    Aug 2010
    Posts
    99
    Thanks
    3
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: QSharedPointer with signals and slots

    Well, the problem is that even though i do currently manage new/delete in a single place, other objects may still have a pointer to an object which gets deleted. And while i could notify that other object of it's deletion, i would prefer it to stay alive until this other object is done with it.

    I am wondering if i should use QSharedData and QExplicitlySharedDataPointer (because i don't want copy-on-write) for MyObject. That should allow me to pass it around in the same way you do with most Qt classes, and the data will not get copied. That way (i think) MyObject does the reference counting, rather than a QSharedPointer. Or will i just have the same problems as i do now?

  16. #16
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,364
    Thanks
    3
    Thanked 5,013 Times in 4,791 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: QSharedPointer with signals and slots

    Quote Originally Posted by xtal256 View Post
    other objects may still have a pointer to an object which gets deleted
    If they do then regardless how smart pointers you use, you have no influence on what others do.

    What I usually do is that I don't expose pointers at all. I wrap them into objects and only expose those. Then you can use QSharedPointer or similar solutions to do reference counting on those internal pointers.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  17. #17
    Join Date
    Aug 2010
    Posts
    99
    Thanks
    3
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: QSharedPointer with signals and slots

    Quote Originally Posted by wysota View Post
    What I usually do is that I don't expose pointers at all. I wrap them into objects and only expose those. Then you can use QSharedPointer or similar solutions to do reference counting on those internal pointers.
    So what's the difference between that and using QSharedData and QExplicitlySharedDataPointer? Could you perhaps give me a small example?

  18. #18
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,364
    Thanks
    3
    Thanked 5,013 Times in 4,791 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: QSharedPointer with signals and slots

    There is not much of a difference. You can use QExplicitlySharedDataPointer if you want. The main difference is with QSharedPointer you can also use QWeakPointer where in the other case you only have QExplicitlySharedDataPointer. Apart from that the other difference is that QExplicitlySharedDataPointer allows you to "detach" the data, whereas there is no such concept with QSharedPointer.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  19. #19
    Join Date
    Aug 2010
    Posts
    99
    Thanks
    3
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: QSharedPointer with signals and slots

    So, in my case, i would do something like this (similar to the Employee example):

    Qt Code:
    1. class MyObjectData : public QSharedData {
    2. public:
    3. // data members here
    4. int member1;
    5. QString member2;
    6. // ...
    7.  
    8. MyObjectData(const MyObjectData &other) : // copy contstructor
    9. QSharedData(other),
    10. member1(other.member1),
    11. member2(other.member2) {
    12. }
    13. };
    14.  
    15. class MyObject : public QObject {
    16. Q_OBJECT
    17. private:
    18. QExplicitlySharedDataPointer<MyObject> d;
    19. public:
    20. MyObject() { d = new MyObjectData(); }
    21. MyObject(const MyObject &other) : d (other.d) {}
    22.  
    23. int getMember1() const { return d->member1; }
    24. QString getMember2() const { return d->member2; }
    25. void setMember1(int i) { d->member1 = i; }
    26. void setMember2(QString s) { d->member2 = s; }
    27. };
    To copy to clipboard, switch view to plain text mode 

    But i also have some subclasses, so i suppose i would do this:
    Qt Code:
    1. class SubClassData : public MyObjectData {
    2. public:
    3. // more data members
    4. float subclassMember1;
    5. bool subclassMember2;
    6. // ...
    7.  
    8. SubClassData(const SubClassData &other) :
    9. MyObjectData(other),
    10. member1(other.member1),
    11. member2(other.member2) {
    12. }
    13. };
    14.  
    15. class SubClass : public MyObject {
    16. Q_OBJECT
    17. public:
    18. SubClass() { d = new SubClassData(); }
    19. SubClass(const SubClass &other) : d (other.d) {}
    20.  
    21. int getSubclassMember1() const { return d->subclassMember1; }
    22. QString getSubclassMember2() const { return d->subclassMember2; }
    23. void setSubclassMember1(int i) { d->subclassMember1 = i; }
    24. void setSubclassMember2(QString s) { d->subclassMember2 = s; }
    25. };
    To copy to clipboard, switch view to plain text mode 
    Then i would pass around these objects by value instead of passing a pointer to them.

    That should solve the two questions i had earlier in this thread.
    For connecting to signals, i could pass the address of the MyObject object:
    Qt Code:
    1. MyObject object;
    2. connect(&object, SIGNAL(updated()), something, SLOT(update()));
    To copy to clipboard, switch view to plain text mode 
    And for having the object create an instance of another object which takes a reference to the creator, i could do this:
    Qt Code:
    1. AnotherObject* MyObject::makeAnotherObject() {
    2. return new AnotherObject(*this);
    3. }
    4. // Note: AnotherObject does not need to be reference counted, so a raw pointer can be returned. The caller of this function will take ownership of it. (Perhaps not the best design, but in this case i am only calling this function from one place and i know where the objects are being used).
    To copy to clipboard, switch view to plain text mode 


    wysota, i would be interested to see how you would deal with this problem using QSharedPointer. It sounds like you would just do something similar to my example above, but replace QExplicitlySharedDataPointer with QSharedPointer and not have MyObjectData inherit from QSharedData. Is that right?

  20. #20
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,364
    Thanks
    3
    Thanked 5,013 Times in 4,791 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: QSharedPointer with signals and slots

    This is all wrong, you can't copy objects that inherit QObject. You have to let the QObject legacy go. If you make the private object inherit QObject then detaching will also not make sense and thus you should use QSharedPointer.

    The more I think of this, the more I come to a conclusion that you should simply not worry about the object being deleted and just use QPointer or QWeakPointer to detect such situations in the object keeping a weak (i.e. unowned) pointer to the object. If someone deletes that object behind your back then simply don't access it anymore.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  21. The following user says thank you to wysota for this useful post:

    xtal256 (7th July 2012)

Similar Threads

  1. Replies: 1
    Last Post: 10th August 2011, 17:46
  2. about signals and slots
    By Sandip in forum Qt Programming
    Replies: 9
    Last Post: 15th July 2008, 17:02
  3. Signals and Slots
    By 83.manish in forum Qt Programming
    Replies: 3
    Last Post: 30th June 2008, 11:31
  4. help with signals and slots
    By superutsav in forum Qt Programming
    Replies: 3
    Last Post: 4th May 2006, 13:49
  5. Signals and Slots in dll
    By ankurjain in forum Qt Programming
    Replies: 8
    Last Post: 29th March 2006, 09:12

Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.