Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. QDataStream serialze & deserialize 'myclass' pointer
Forum Updated to NodeBB v4.3 + New Features

QDataStream serialze & deserialize 'myclass' pointer

Scheduled Pinned Locked Moved Solved General and Desktop
24 Posts 4 Posters 8.9k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • Taz742T Offline
    Taz742T Offline
    Taz742
    wrote on last edited by Taz742
    #1

    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.

    Do what you want.

    1 Reply Last reply
    0
    • B Offline
      B Offline
      bludger
      wrote on last edited by
      #2

      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.

      Taz742T 1 Reply Last reply
      1
      • B bludger

        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.

        Taz742T Offline
        Taz742T Offline
        Taz742
        wrote on last edited by Taz742
        #3

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

        Do what you want.

        1 Reply Last reply
        0
        • VRoninV Offline
          VRoninV Offline
          VRonin
          wrote on last edited by
          #4

          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

          "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
          ~Napoleon Bonaparte

          On a crusade to banish setIndexWidget() from the holy land of Qt

          Taz742T 1 Reply Last reply
          0
          • VRoninV VRonin

            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

            Taz742T Offline
            Taz742T Offline
            Taz742
            wrote on last edited by
            #5

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

            Do what you want.

            1 Reply Last reply
            0
            • VRoninV Offline
              VRoninV Offline
              VRonin
              wrote on last edited by VRonin
              #6

              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

              "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
              ~Napoleon Bonaparte

              On a crusade to banish setIndexWidget() from the holy land of Qt

              Taz742T 1 Reply Last reply
              0
              • VRoninV VRonin

                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

                Taz742T Offline
                Taz742T Offline
                Taz742
                wrote on last edited by
                #7

                @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.

                Do what you want.

                1 Reply Last reply
                0
                • VRoninV Offline
                  VRoninV Offline
                  VRonin
                  wrote on last edited by VRonin
                  #8

                  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>

                  "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                  ~Napoleon Bonaparte

                  On a crusade to banish setIndexWidget() from the holy land of Qt

                  Taz742T 1 Reply Last reply
                  4
                  • VRoninV VRonin

                    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>

                    Taz742T Offline
                    Taz742T Offline
                    Taz742
                    wrote on last edited by Taz742
                    #9

                    @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?

                    Do what you want.

                    kshegunovK 1 Reply Last reply
                    0
                    • Taz742T Taz742

                      @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?

                      kshegunovK Offline
                      kshegunovK Offline
                      kshegunov
                      Moderators
                      wrote on last edited by
                      #10

                      @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.

                      Read and abide by the Qt Code of Conduct

                      Taz742T 1 Reply Last reply
                      1
                      • kshegunovK kshegunov

                        @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.

                        Taz742T Offline
                        Taz742T Offline
                        Taz742
                        wrote on last edited by Taz742
                        #11

                        @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;
                            }
                        

                        Do what you want.

                        kshegunovK 1 Reply Last reply
                        0
                        • Taz742T Taz742

                          @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;
                              }
                          
                          kshegunovK Offline
                          kshegunovK Offline
                          kshegunov
                          Moderators
                          wrote on last edited by
                          #12

                          @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;
                          

                          Read and abide by the Qt Code of Conduct

                          Taz742T 1 Reply Last reply
                          2
                          • kshegunovK kshegunov

                            @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;
                            
                            Taz742T Offline
                            Taz742T Offline
                            Taz742
                            wrote on last edited by Taz742
                            #13

                            @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;
                                               ^
                            

                            Do what you want.

                            kshegunovK 1 Reply Last reply
                            0
                            • Taz742T Taz742

                              @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;
                                                 ^
                              
                              kshegunovK Offline
                              kshegunovK Offline
                              kshegunov
                              Moderators
                              wrote on last edited by
                              #14

                              Did you forget to include the <QDataStream> header?

                              Read and abide by the Qt Code of Conduct

                              Taz742T 1 Reply Last reply
                              1
                              • kshegunovK kshegunov

                                Did you forget to include the <QDataStream> header?

                                Taz742T Offline
                                Taz742T Offline
                                Taz742
                                wrote on last edited by
                                #15

                                @kshegunov no. I have

                                Do what you want.

                                kshegunovK 1 Reply Last reply
                                0
                                • Taz742T Taz742

                                  @kshegunov no. I have

                                  kshegunovK Offline
                                  kshegunovK Offline
                                  kshegunov
                                  Moderators
                                  wrote on last edited by
                                  #16

                                  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.

                                  Read and abide by the Qt Code of Conduct

                                  Taz742T 1 Reply Last reply
                                  2
                                  • kshegunovK kshegunov

                                    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.

                                    Taz742T Offline
                                    Taz742T Offline
                                    Taz742
                                    wrote on last edited by Taz742
                                    #17

                                    @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.

                                    Do what you want.

                                    kshegunovK 1 Reply Last reply
                                    0
                                    • Taz742T Taz742

                                      @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.

                                      kshegunovK Offline
                                      kshegunovK Offline
                                      kshegunov
                                      Moderators
                                      wrote on last edited by
                                      #18

                                      @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.

                                      Read and abide by the Qt Code of Conduct

                                      Taz742T 2 Replies Last reply
                                      0
                                      • kshegunovK kshegunov

                                        @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.

                                        Taz742T Offline
                                        Taz742T Offline
                                        Taz742
                                        wrote on last edited by
                                        #19

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

                                        Do what you want.

                                        1 Reply Last reply
                                        0
                                        • kshegunovK kshegunov

                                          @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.

                                          Taz742T Offline
                                          Taz742T Offline
                                          Taz742
                                          wrote on last edited by Taz742
                                          #20

                                          @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?

                                          Do what you want.

                                          kshegunovK 1 Reply Last reply
                                          0

                                          • Login

                                          • Login or register to search.
                                          • First post
                                            Last post
                                          0
                                          • Categories
                                          • Recent
                                          • Tags
                                          • Popular
                                          • Users
                                          • Groups
                                          • Search
                                          • Get Qt Extensions
                                          • Unsolved