How do you serialize an object in C++?

In some cases, when dealing with simple types, you can do:

object o;
socket.write(&o, sizeof(o));

That's ok as a proof-of-concept or first-draft, so other members of your team can keep working on other parts.

But sooner or later, usually sooner, this will get you hurt!

You run into issues with:

  • Virtual pointer tables will be corrupted.
  • Pointers (to data/members/functions) will be corrupted.
  • Differences in padding/alignment on different machines.
  • Big/Little-Endian byte ordering issues.
  • Variations in the implementation of float/double.

(Plus you need to know what you are unpacking into on the receiving side.)

You can improve upon this by developing your own marshalling/unmarshalling methods for every class. (Ideally virtual, so they can be extended in subclasses.) A few simple macros will let you to write out different basic types quite quickly in a big/little-endian-neutral order.

But that sort of grunt work is much better, and more easily, handled via boost's serialization library.


Talking about serialization, the boost serialization API comes to my mind. As for transmitting the serialized data over the net, I'd either use Berkeley sockets or the asio library.

If you want to serialize your objects to a byte array, you can use the boost serializer in the following way (taken from the tutorial site):

#include <boost/archive/binary_oarchive.hpp>
#include <boost/archive/binary_iarchive.hpp>
class gps_position
{
private:
    friend class boost::serialization::access;
    template<class Archive>
    void serialize(Archive & ar, const unsigned int version)
    {
        ar & degrees;
        ar & minutes;
        ar & seconds;
    }
    int degrees;
    int minutes;
    float seconds;

public:
    gps_position(){};
    gps_position(int d, int m, float s) :
    degrees(d), minutes(m), seconds(s)
    {}
};

Actual serialization is then pretty easy:

#include <fstream>
std::ofstream ofs("filename.dat", std::ios::binary);

    // create class instance
    const gps_position g(35, 59, 24.567f);

    // save data to archive
    {
        boost::archive::binary_oarchive oa(ofs);
        // write class instance to archive
        oa << g;
        // archive and stream closed when destructors are called
    }

Deserialization works in an analogous manner.

There are also mechanisms which let you handle serialization of pointers (complex data structures like tress etc are no problem), derived classes and you can choose between binary and text serialization. Besides all STL containers are supported out of the box.