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.
-
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.
-
You are leaking memory like a bandit here.
QList<myclass>
here instead ofQVector<myclass*>
is as efficient, less prone to memory leaks and doesn't require you to hackoperator>>
andoperator<<
for pointers type -
yes but you wouldn't have to hack your way through it. You'd implement
QDataStream & operator << (QDataStream &stream, const myclass& cls)
andQDataStream & operator >> (QDataStream &stream, myclass& cls)
QList doesn't require a copy of the elements when it grows in size -
yes but you wouldn't have to hack your way through it. You'd implement
QDataStream & operator << (QDataStream &stream, const myclass& cls)
andQDataStream & operator >> (QDataStream &stream, myclass& cls)
QList doesn't require a copy of the elements when it grows in size -
you can imagine both
QVector<T>(n)
andstd::vector<T>(n)
as wrappers aroundT* vec = new T[n]
whileQList<T>(n)
can be imagined as a wrapper aroundT** 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 othersQVector<myclass*>
containing heap allocated objects thatQVector
(should) own is, in practice, the same asQList<myclass>
-
you can imagine both
QVector<T>(n)
andstd::vector<T>(n)
as wrappers aroundT* vec = new T[n]
whileQList<T>(n)
can be imagined as a wrapper aroundT** 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 othersQVector<myclass*>
containing heap allocated objects thatQVector
(should) own is, in practice, the same asQList<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?
-
@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?
@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.
-
@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; }
-
@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; }
@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;
-
@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.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; ^
-
@kshegunov good :))
Now there are new problems.
Recently everything was good.
I do not know what happened to me or why.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; ^
Did you forget to include the
<QDataStream>
header? -
@kshegunov no. I have
-
@kshegunov no. I have
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 69error: 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 &
notQDataStream
. Please post what's on line 69 inenumeration.h
. -
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 69error: 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 &
notQDataStream
. Please post what's on line 69 inenumeration.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. -
@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.@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.
-
@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.
-
@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 @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?