QDataStream serialze & deserialize 'myclass' pointer



  • hello all.
    i have a problem serialize and deserialize datastream class pointer.

    #include "mainwindow.h"
    #include <QApplication>
    #include "QDebug"
    #include "QDataStream"
    #include "QByteArray"
    
    class myclass
    {
        public:
            int x;
            int y;
            bool ok;
            QString message;
            myclass(){}
            myclass(int _x, int _y, bool _ok, QString _str) {
                this->x = _x;
                this->y = _y;
                this->ok = _ok;
                this->message = _str;
            }
    };
    
    void print(myclass *cls) {
        qDebug() << "answer: " << cls->x << cls->y >> cls->ok >> cls->message;
    }
    
    QDataStream & operator << (QDataStream &stream, const myclass *cls) {
        stream << static_cast<qint32>(cls->x) << static_cast<qint32>(cls->y) << cls->ok << cls->message;
    
        return stream;
    }
    
    QDataStream & operator >> (QDataStream &stream, myclass * cls) {
        qint32 tmpint;
        stream >> tmpint; cls->x = tmpint; //crash this line
        stream >> tmpint; cls->y = tmpint;
    
        return stream >> cls->ok >> cls->message;
    }
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
    
    //    MainWindow w;
    
    //    w.show();
    
        QByteArray buff;
        QDataStream in(&buff, QIODevice::ReadWrite);
        in.setVersion(QDataStream::Qt_5_5);
    
        QMap<int, QVector<myclass*> > mp;
    
        mp[1].push_back(new myclass(1, 3, 0, "foo"));
        mp[2].push_back(new myclass(351, 5, 0, "bar"));
    
        in << mp;
    
        QDataStream out(&buff, QIODevice::ReadWrite);
        out.setVersion(QDataStream::Qt_5_5);
    
        QMap<int, QVector<myclass*> > mp1;
        QMap<int, QVector<myclass*> > ::iterator it;
    
        out >> mp1;
    
        for (it = mp1.begin(); it != mp1.end(); it++) {
            foreach (myclass *pr, mp1[it.key()]) {
                print(pr);
            }
        }
    
        return a.exec();
    }
    
    
    • I wonder why so?
    • can you help me and fixed this problem?

    If I do not use a pointer everything is fine.



  • Hi,

    Your main issue is that the pointer passed to your stream operator is uninitialized.
    Thereby the stream operator should have another signature:

    QDataStream& operator>>(QDataStream& in, myclasss *& obj);
    

    Note that the second parameter is a reference to a pointer. We need this in order to do the following:

    QDataStream& operator>>(QDataStream& in, myclass*& obj) {
      obj = new myclass(); // pointer now correctly initialized 
      in >> obj->property;
      return in;
    }
    

    This should fix it.



  • @bludger hm... i am stupid? :d
    many thank friend, its fixed :)



  • You are leaking memory like a bandit here.

    QList<myclass> here instead of QVector<myclass*> is as efficient, less prone to memory leaks and doesn't require you to hack operator>> and operator<< for pointers type



  • @VRonin waitttt. If I use QList, I will not have to teach DataStream how to arrange my class?



  • yes but you wouldn't have to hack your way through it. You'd implement QDataStream & operator << (QDataStream &stream, const myclass& cls) and QDataStream & operator >> (QDataStream &stream, myclass& cls)
    QList doesn't require a copy of the elements when it grows in size



  • @VRonin I still use std :: vector <T> when I write programmatic tasks.
    It's so deeply in my subconscious that I'm not trying to see what QList gives me better than QVector.



  • you can imagine both QVector<T>(n) and std::vector<T>(n) as wrappers around T* vec = new T[n] while QList<T>(n) can be imagined as a wrapper around T** vec=new T*[n]; for(int i=0;i<n;++i) vec[i] = new T;

    Now imagine inserting an item in the middle in those 2 cases.

    That's why the docs suggests using QVector for types that are Q_MOVABLE_TYPE (the name can be misleading, see Q_DECLARE_TYPEINFO) and QList for the others

    QVector<myclass*> containing heap allocated objects that QVector (should) own is, in practice, the same as QList<myclass>



  • @VRonin Do you mean this?

           if (query.exec()) {
                QList<Contact> *_list = new QList<Contact>();
                while (query.next()) {
                    _list->push_back(Contact(query.value("UID").toInt(),
                                             query.value("USERNAME").toString(),
                                             query.value("MOBILE").toString(),
                                             )
                                     );
                }
    
                qDebug() << _list->size();
    
                QByteArray bytes;
                QDataStream stream(&bytes, QIODevice::WriteOnly);
                stream << sSelecAllContacts << _list;
                globalall->modify(bytes);
                socket->write(bytes);
            }
    

    I have just one pointer now?


  • Qt Champions 2016

    @Taz742 said in QDataStream serialze & deserialize 'myclass' pointer:

    @VRonin Do you mean this?

    No. He means this:

    QList<Contact> _list;
    while (query.next()) {
        _list.push_back(Contact(query.value("UID").toInt(),
            query.value("USERNAME").toString(),
            query.value("MOBILE").toString(),
        ));
    }
    

    There is no gain at all in creating a Qt container in the heap.



  • @kshegunov
    Well, let's consider this case.
    What I wrote this is the server side.

    When I get it to the client side, if I get the same kind of list and get the value from it.
    for example:

        QList<faf> list;
    
        list.push_back(faf(2, 13));
        list.push_back(faf(15, 23));
        list.push_back(faf(30, 46));
    
        faf test = list[0];
        test.x = test.x * 2;
        test.y = test.y * 2;
    
        for (int i = 0; i < list.size(); i++) {
            qDebug() << list[i].x << list[i].y; //Prints the same values
        }
    
    
    

    If I want the object to change in the list.
    Is it right?

        QList<faf> list;
    
        list.push_back(faf(2, 13));
        list.push_back(faf(15, 23));
        list.push_back(faf(30, 46));
    
        faf *test = &list[0];
        test->x = test->x * 2;
        test->y = test->y * 2;
    
        for (int i = 0; i < list.size(); i++) {
            qDebug() << list[i].x << list[i].y; //list[0].x = 4 and list[0].y = 46;
        }
    

  • Qt Champions 2016

    @Taz742 said in QDataStream serialze & deserialize 'myclass' pointer:

    // Prints the same values
    

    Of course it does, you're copying the object that's stored in the list and modifying the copy.

    If I want the object to change in the list.

    Why convert to pointers? Just use references:

    faf & test = list[0];
    test.x *= 2;
    test.y *= 2;
    


  • @kshegunov good :))

    Now there are new problems.
    Recently everything was good.
    I do not know what happened to me or why.

    alt text

    C:\Users\User\Desktop\tazsmsorigin\enumeration.h:69: error: no match for 'operator>>' (operand types are 'QDataStream' and 'qint32 {aka int}')
         stream >> tempint; _class.UID = tempint;
                ^
    C:\Users\User\Desktop\tazsmsorigin\enumeration.h:50: error: ambiguous overload for 'operator<<' (operand types are 'QDataStream' and 'int')
         stream  << static_cast<qint32>(_class.UID)
                 ^
    C:\Users\User\Desktop\tazsmsorigin\enumeration.h:46: error: no match for 'operator>>' (operand types are 'QDataStream' and 'bool')
         return stream >> _class.TChecked >> _class.Message;
                       ^
    

  • Qt Champions 2016

    Did you forget to include the <QDataStream> header?



  • @kshegunov no. I have


  • Qt Champions 2016

    Then you need to follow the compiler errors, it has given you exact directions where the errors are:
    C:\Users\User\Desktop\tazsmsorigin\enumeration.h @ line 69

    error: no match for 'operator>>' (operand types are 'QDataStream' and 'qint32 {aka int}')

    I'm pretty sure this comes from not including the header. Also there's something amiss, it should be QDataStream & not QDataStream. Please post what's on line 69 in enumeration.h.



  • @kshegunov
    Yes the library was nat included, but I had it in globaldefines.h file.
    He has caused a redifination proxy, QDataStream also has been described in MySocket.h file.


  • Qt Champions 2016

    @Taz742 said in QDataStream serialze & deserialize 'myclass' pointer:

    He has caused a redifination proxy, QDataStream also has been described in MySocket.h file.

    I don't follow.



  • @kshegunov I had code again mysocket.h, I taught at different places how to deal with my classes.



  • @kshegunov @VRonin
    How to handle QDataStream to my classes, this are stored in one 'header' file.
    It's uncomfortable for me because I have many issues.
    I learnt to my classes QDataStream >> and << operators.

    For Example:

    #ifndef POINT3D_H
    #define POINT3D_H
    
    #include "QObject"
    #include "QDataStream"
    
    class Point3D
    {
    public:
        Point3D();
        int x;
        int y;
        int z;
    
        Point3D(int _x, int _y, int _z) {
            this->x = _x;
            this->y = _y;
            this->z = _z;
        }
    
        friend QDataStream & operator << (QDataStream &stream, const Point3D &obj);
        friend QDataStream & operator >> (QDataStream &stream, Point3D &obj);
    };
    
    Q_DECLARE_TYPEINFO(Point3D, Q_MOVABLE_TYPE);
    
    #endif // POINT3D_H
    
    #include "point3d.h"
    
    Point3D::Point3D()
    {
    
    }
    
    QDataStream & operator << (QDataStream &stream, const Point3D &obj) {
        stream << static_cast<qint32>(obj.x) << static_cast<qint32>(obj.y) << static_cast<qint32>(obj.z);
        return stream;
    }
    
    QDataStream & operator >> (QDataStream &stream, Point3D &obj) {
        qint32 tempint;
        stream >> tempint; obj.x = static_cast<int>(tempint);
        stream >> tempint; obj.y = static_cast<int>(tempint);
        stream >> tempint; obj.z = static_cast<int>(tempint);
    
        return stream;
    }
    

    I want to be sure that this will work from anywhere. Can you confirm it?


  • Qt Champions 2016

    @Taz742 said in QDataStream serialze & deserialize 'myclass' pointer:

    I want to be sure that this will work from anywhere. Can you confirm it?

    I don't understand the question, could you elaborate.



  • @kshegunov said in QDataStream serialze & deserialize 'myclass' pointer:

    I don't understand the question, could you elaborate.

    I have class Point3D which know how to behave when datastream requires input(<<) or output(>>) operators.
    I want to know if it will works from anyclasses, for example: from mainwindows and etc..


  • Qt Champions 2016

    Why wouldn't it? As long as the functions have declarations at the point of usage it's the linker's problem to tie it all together ... it's the singular purpose for which the linker exists actually.



  • @kshegunov Now I'm sure. thanks.


Log in to reply
 

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