There are several classes, they are nested in each other (in the first class, the second vector, in each second, the third vector) and have their own attributes. I tried to write and read like this:

fout.write(reinterpret_cast<char*>(&pr1), sizeof(pr1));//pr1 объект класса in.read(reinterpret_cast<char*>(&pr1_copy), sizeof(pr1_copy)); 

The problem is that such a record + reading only works together, we write addresses from an existing object, and if you delete pr1 before reading from a file, nothing will be written to pr_copy, because those addresses will have garbage / empty. Therefore, the question is: how to make a normal recording of an object in a binary file, so that, for example, it can be read from another project?

  • QT do not use? There serialization is somewhat simpler. - Alexander Petrov
  • You can also look in the direction of Protocol Buffers (protobuf). - Alexander Petrov

2 answers 2

Develop a non-trivial serialization system that will carefully view your object as a set of stable pieces and then write piece-by-piece your object into a binary file so that later when reading these pieces from the file you can restore the original state of the object. Of course, there can be no talk of any record by “one write ”, and there can be no talk of direct writing of pointers either.

  • one
    In C ++, there are no libraries for doing such scams? I can’t imagine how I’ll write this .. (the vectors can be of different sizes, how to take it into account when reading .. - Alex
  • @Alex Alternatively, define the template<class... Params> std::basic_ostream<Params...> &operator<<(std::basic_ostream<Params...> &, Class const &) , within which to paint the entire marshalling , ancestor after ancestor, field after field. Well, operator>> respectively. - bipll
  • As an option, refer to the ASN1 type syntax notations when writing and reading. There are serialization libraries for this type. - NewView

Well, let's try ... Let's start from the inside. Let us have, for simplicity,

 struct Inner { vector<int> data; }; 

Add to it the functions of reading and writing to the file. The main thing - they must be consistent and write and read one format. For example:

 struct Inner { vector<int> data; ifstream& read(ifstream& in) { data.clear(); size_t sz; in.read((char*)&sz,sizeof(sz)); data.resize(sz); in.read((char*)&data[0],sizeof(sz)); } ofstream& write(ofstream& out) { size_t sz = data.size(); out.write((char*)&sz,sizeof(sz)); out.write((char*)&data[0],sizeof(int)*sz); return out; } }; 

And may we now have

 struct Outer { vector<Inner> data; }; 

Let's write exactly the same functions, only now when we write the vector, we will write the elements separately, one by one, without worrying about how this is done - the elements themselves will do this:

 struct Outer { vector<Inner> data; ifstream& read(ifstream& in) { data.clear(); size_t sz; in.read((char*)&sz,sizeof(sz)); for(int i = 0; i < sz; ++i) { Inner iobj; iobj.read(in); data.push_back(iobj); } return in; } ofstream& write(ofstream& out) { size_t sz = data.size(); out.write((char*)&sz,sizeof(sz)); for(int i = 0; i < sz; ++i) { Inner& iobj = data[i]; iobj.write(out); } return out; } }; 

Imagine that we also have a char* field, a pointer to a string. We will add its record-reading:

 struct Outer { vector<Inner> data; char * s; ifstream& read(ifstream& in) { data.clear(); size_t sz; in.read((char*)&sz,sizeof(sz)); for(int i = 0; i < sz; ++i) { Inner iobj; iobj.read(in); data.push_back(iobj); } in.read((char*)&sz,sizeof(sz)); delete[] s; s = new char[sz]; in.read(s,sz); return in; } ofstream& write(ofstream& out) { size_t sz = data.size(); out.write((char*)&sz,sizeof(sz)); for(int i = 0; i < sz; ++i) { Inner& iobj = data[i]; iobj.write(out); } sz = strlen(s)+1; out.write((char*)&sz,sizeof(sz)); out.write(s,sz); return out; } }; 

And so - for all fields, and if the fields are complex - their classes, then it is better to deal with them yourself ...

Write a read-write for

 struct Envelope { vector<Outer> data; }; 

Can you do it yourself now? :)