Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Serializing a class which contains a std::string

I'm not a c++ expert but I've serialized things a couple of times in the past. Unfortunately this time I'm trying to serialize a class which contains a std::string, which I understand is pretty much like serializing a pointer.

I can write out the class to a file and read it back in again. All int fields are fine but the std::string field gives an "address out of bounds" error, presumably because it points to data which is no longer there.

Is there a standard workaround for this? I don't want to go back to char arrays but at least I know they work in this situation. I can provide code if necessary but I'm hoping I've explained my problem well.

I'm serializing by casting the class to a char* and writing it to a file with fstream. Reading of course is just the reverse.

like image 833
iwasinnamuknow Avatar asked Aug 12 '11 20:08

iwasinnamuknow


1 Answers

I'm serializing by casting the class to a char* and writing it to a file with fstream. Reading of course is just the reverse.

Unfortunately, this only works as long as there are no pointers involved. You might want to give your classes void MyClass::serialize(std::ostream) and void MyClass::deserialize(std::ifstream), and call those. For this case, you'd want

std::ostream& MyClass::serialize(std::ostream &out) const {
    out << height;
    out << ',' //number seperator
    out << width;
    out << ',' //number seperator
    out << name.size(); //serialize size of string
    out << ',' //number seperator
    out << name; //serialize characters of string
    return out;
}
std::istream& MyClass::deserialize(std::istream &in) {
    if (in) {
        int len=0;
        char comma;
        in >> height;
        in >> comma; //read in the seperator
        in >> width;
        in >> comma; //read in the seperator
        in >> len;  //deserialize size of string
        in >> comma; //read in the seperator
        if (in && len) {
            std::vector<char> tmp(len);
            in.read(tmp.data() , len); //deserialize characters of string
            name.assign(tmp.data(), len);
        }
    }
    return in;
}

You may also want to overload the stream operators for easier use.

std::ostream &operator<<(std::ostream& out, const MyClass &obj)
{obj.serialize(out); return out;}
std::istream &operator>>(std::istream& in, MyClass &obj)
{obj.deserialize(in); return in;}
like image 69
Mooing Duck Avatar answered Sep 20 '22 05:09

Mooing Duck