[SOLVED] When can I use Q_DECLARE_TYPEINFO() with Q_MOVABLE_TYPE ?



  • According to "nice article at doobs":http://www.drdobbs.com/c-made-easier-plain-old-data/184401508 , we should not use memcpy() when copying a object that has constructor or destructor(std::string was the good example in that article). But I found following statements in Qt doc

    @

    // Example of a movable type:

    class Point2D
    {
    public:
    Point2D() { data = new int[2]; }
    Point2D(const Point2D &other) { ... }
    ~Point2D() { delete[] data; }

     Point2D &operator=(const Point2D &other) { ... }
    
     int x() const { return data[0]; }
     int y() const { return data[1]; }
    

    private:
    int *data;
    };

    Q_DECLARE_TYPEINFO(Point2D, Q_MOVABLE_TYPE);
    @

    The Point2D class has constructor and destructor but can we use memcpy(or memmove) with it?

    the

    @int* data@

    member seems to be heap allocated and assignment operator could do deep-copy it.
    According to Qt doc, it sounds like we can use following decl for std::string.

    @
    namespace std {
    Q_DECLARE_TYPEINFO(string, Q_MOVABLE_TYPE);
    }
    @

    Little bit confused. is it ok for me to do that for std::string?

    Might be Qt doc say that 'moving'(NOT 'copying') is ok in this case.



  • memcpy() can be a bit misleading here, as it is a matter of definition whether an object is copied (the object at const void* source is still valid after the operation) or moved (the object at const void* source is no longer valid after the operation).

    There is no such thing as memory beeing moved; it is always a copy operation with the former memory region beeing declared invalid. The difference between memcpy() and memmove() is that memmove() can be use to copy overlapping memory regions (at a performance cost compared to memcopy()), but both copy.

    A Q_MOVABLE_TYPE can be moved using memcpy() (instead of the copy constructor), but not necessarily copied.

    A Point2D object can be freely moved in memory using memcpy(), as int *data still points to a valid memory region. It cannot be, however, copied using memcpy(), as both int *data would point to the same memory region.

    Whether this is true for std::string purely depends on the implementation of std::string in the used standard library, it might be, but it also might not be. This is why the Q_MOVABLE_TYPE type info is usually set by the author of the class in question, not the user.

    QString is, as all implictly shared classes, a Q_MOVABLE_TYPE.

    Be aware that there is a difference between movable as in move semantics in terms of providing a move constructor and move assignment operator and movable in terms of beeing able to be moved using memcpy(); this is why it is mentioned in the documentation.



  • Thanks for your greate answer. It shed light on my mind.
    One things is still under question though. Any simple example of a class that can not be 'Q_MOVABLE_TYPE' ?



  • Non-movable classes are for instance any classes which use a "Q-Pointer":http://techbase.kde.org/Policies/Library_Code_Policy#Q-Pointers, like QObject, as moving would lead to a dangling Q-Pointer.



  • Thanks. Crystalized.



  • You're welcome! ;-)


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.