iostream::write for a composite class

Discussion in 'C++' started by kk_oop@yahoo.com, Jul 19, 2008.

  1. Guest

    Consider class X and Y where:

    class X
    {
    double d;
    int i;
    Y myY;
    };

    class Y
    {
    int h;
    int g;
    };

    If I pass the address of an instance of X (cast to a char *) to a
    binary ofstream's write() method, indicating sizeof(X) as the size of
    the data, would that write out all of X, including the state of its Y
    instance?

    Thanks!

    Ken
    , Jul 19, 2008
    #1
    1. Advertising

  2. Guest

    On Jul 19, 7:50 pm, wrote:
    > Consider class X and Y where:
    >
    > class X
    > {
    >   double d;
    >   int i;
    >   Y myY;
    >
    > };
    >
    > class Y
    > {
    >   int h;
    >   int g;
    >
    > };
    >
    > If I pass the address of an instance of X (cast to a char *) to a
    > binary ofstream's write() method, indicating sizeof(X) as the size of
    > the data, would that write out all of X, including the state of its Y
    > instance?
    >
    > Thanks!
    >
    > Ken


    Sure, here's an example:

    #include <iostream>
    #include <fstream>
    using namespace std;

    struct X
    {
    int x;
    int y;
    };

    struct Y
    {
    int a;
    int b;
    X x;
    };

    int main()
    {
    Y y;

    y.a = 1;
    y.b = 2;
    y.x.x = 3;
    y.x.y = 4;

    ofstream out( "tmp.bin", ios_base::binary );
    out.write( reinterpret_cast< char* >( &y ), sizeof( Y ) );
    out.close();

    ifstream in( "tmp.bin", ios_base::binary );
    Y y2;
    in.read( reinterpret_cast< char* >( &y2 ), sizeof( Y ) );

    cout << "y2.a=" << y2.a << endl;
    cout << "y2.b=" << y2.b << endl;
    cout << "y2.x.x=" << y2.x.x << endl;
    cout << "y2.x.y=" << y2.x.y << endl;
    }

    But if you are interested in object boost has some very useful
    classes: http://www.boost.org/doc/libs/1_35_0/libs/serialization/doc/index.html
    , Jul 19, 2008
    #2
    1. Advertising

  3. Barry Guest

    wrote:
    > Consider class X and Y where:
    >
    > class X
    > {
    > double d;
    > int i;
    > Y myY;
    > };
    >
    > class Y
    > {
    > int h;
    > int g;
    > };


    Practically you have to define Y before you declare the member 'myY' as
    type of Y.

    >
    > If I pass the address of an instance of X (cast to a char *) to a
    > binary ofstream's write() method, indicating sizeof(X) as the size of
    > the data, would that write out all of X, including the state of its Y
    > instance?


    Yes

    --
    Best Regards
    Barry
    Barry, Jul 19, 2008
    #3
  4. On Jul 19, 11:25 am, wrote:
    > On Jul 19, 7:50 pm, wrote:
    >
    >
    >
    > > Consider class X and Y where:

    >
    > > class X
    > > {
    > > double d;
    > > int i;
    > > Y myY;

    >
    > > };

    >
    > > class Y
    > > {
    > > int h;
    > > int g;

    >
    > > };

    >
    > > If I pass the address of an instance of X (cast to a char *) to a
    > > binary ofstream's write() method, indicating sizeof(X) as the size of
    > > the data, would that write out all of X, including the state of its Y
    > > instance?

    >
    > > Thanks!

    >
    > > Ken

    >
    > Sure, here's an example:
    >
    > #include <iostream>
    > #include <fstream>
    > using namespace std;
    >
    > struct X
    > {
    > int x;
    > int y;
    >
    > };
    >
    > struct Y
    > {
    > int a;
    > int b;
    > X x;
    >
    > };
    >
    > int main()
    > {
    > Y y;
    >
    > y.a = 1;
    > y.b = 2;
    > y.x.x = 3;
    > y.x.y = 4;
    >
    > ofstream out( "tmp.bin", ios_base::binary );
    > out.write( reinterpret_cast< char* >( &y ), sizeof( Y ) );
    > out.close();
    >
    > ifstream in( "tmp.bin", ios_base::binary );
    > Y y2;
    > in.read( reinterpret_cast< char* >( &y2 ), sizeof( Y ) );
    >
    > cout << "y2.a=" << y2.a << endl;
    > cout << "y2.b=" << y2.b << endl;
    > cout << "y2.x.x=" << y2.x.x << endl;
    > cout << "y2.x.y=" << y2.x.y << endl;
    >
    > }

    Argh, avoid this, you hear me - AVOID this. reinterpret_cast is
    equal to trouble in 99% of cases (and no one is aware of 1%, we just
    have it to be politically correct). This is likely not to work if you
    serialize this way on one machine, and deserialize on another;
    certainly won't work on machines with different indianess, 32 vs. 64
    bits, you name it.

    Just write your own ostream<< operator to write to a file, lest
    succumb to poorly implemented features which wreak more havoc than
    provide a panacea.


    Add this to your classes, if you can:

    friend ostream & operator << (ostream &os, const X & o);
    friend ostream & operator << (ostream &os, const Y & o);
    puzzlecracker, Jul 20, 2008
    #4
  5. James Kanze Guest

    On Jul 19, 1:50 pm, wrote:
    > Consider class X and Y where:


    > class X
    > {
    > double d;
    > int i;
    > Y myY;
    > };


    > class Y
    > {
    > int h;
    > int g;
    > };


    > If I pass the address of an instance of X (cast to a char *)
    > to a binary ofstream's write() method, indicating sizeof(X) as
    > the size of the data, would that write out all of X, including
    > the state of its Y instance?


    Maybe. That's going to require a reinterpret_cast, so whatever
    happens is really implementation defined. But you'll probably
    find all of the bits you want in there somewhere. Plus perhaps
    a few others, and of course, in an unspecified order.

    Basically, using ostream::write is fine, but unless the data
    you're writing is preformatted into a buffer of char, you can't
    count on being able to reread it in any way.

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
    James Kanze, Jul 20, 2008
    #5
  6. James Kanze Guest

    On Jul 20, 1:43 am, puzzlecracker <> wrote:
    > On Jul 19, 11:25 am, wrote:


    [...]
    > Argh, avoid this, you hear me - AVOID this. reinterpret_cast is
    > equal to trouble in 99% of cases (and no one is aware of 1%, we just
    > have it to be politically correct).


    I am. Ever try to write a garbage collector:).

    (But your comments are right on target here.)

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
    James Kanze, Jul 20, 2008
    #6
  7. Guest

    On Jul 19, 11:25 am, wrote:
    > On Jul 19, 7:50 pm, wrote:
    >

    <<snip>>
    >


    > Sure, here's an example:
    >
    > #include <iostream>
    > #include <fstream>
    > using namespace std;
    >
    > struct X
    > {
    >         int x;
    >         int y;
    >
    > };
    >
    > struct Y
    > {
    >         int a;
    >         int b;
    >         X x;
    >
    > };
    >
    > int main()
    > {
    >         Y y;
    >
    >         y.a = 1;
    >         y.b = 2;
    >         y.x.x = 3;
    >         y.x.y = 4;
    >
    >         ofstream out( "tmp.bin", ios_base::binary );
    >         out.write( reinterpret_cast< char* >( &y ), sizeof( Y ) );
    >         out.close();
    >
    >         ifstream in( "tmp.bin", ios_base::binary );
    >         Y y2;
    >         in.read( reinterpret_cast< char* >( &y2 ), sizeof( Y ) );
    >
    >         cout << "y2.a=" << y2.a << endl;
    >         cout << "y2.b=" << y2.b << endl;
    >         cout << "y2.x.x=" << y2.x.x << endl;
    >         cout << "y2.x.y=" << y2.x.y << endl;
    >
    > }
    >
    > But if you are interested in object boost has some very useful
    > classes:http://www.boost.org/doc/libs/1_35_0/libs/serialization/doc/index..html


    Would this break if X or Y has a virtual function? Would sizeof then
    include the pointer to the virtual table--and would write() try to
    write that information?

    Thanks again,

    Ken
    , Jul 20, 2008
    #7
  8. James Kanze Guest

    On Jul 20, 12:06 pm, Peter Jansson <> wrote:
    > On Sat, 19 Jul 2008, puzzlecracker wrote:


    > /.../> Argh, avoid this, you hear me - AVOID this. reinterpret_cast is
    > > equal to trouble in 99% of cases (and no one is aware of 1%, we just
    > > have it to be politically correct). This is likely not to work if you
    > > serialize this way on one machine, and deserialize on another;
    > > certainly won't work on machines with different indianess, 32 vs. 64
    > > bits, you name it.


    > /.../


    > Unformatted output and input could be Ok if staying on one
    > machine or one type of machine only.


    And if you never upgrade or change your compiler, and if you
    always compile with exactly the same options.

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
    James Kanze, Jul 20, 2008
    #8
  9. James Kanze Guest

    On Jul 20, 4:06 pm, wrote:
    > On Jul 19, 11:25 am, wrote:
    > > On Jul 19, 7:50 pm, wrote:


    > > Sure, here's an example:


    > > #include <iostream>
    > > #include <fstream>
    > > using namespace std;


    > > struct X
    > > {
    > > int x;
    > > int y;
    > > };


    > > struct Y
    > > {
    > > int a;
    > > int b;
    > > X x;
    > > };


    > > int main()
    > > {
    > > Y y;


    > > y.a = 1;
    > > y.b = 2;
    > > y.x.x = 3;
    > > y.x.y = 4;


    > > ofstream out( "tmp.bin", ios_base::binary );
    > > out.write( reinterpret_cast< char* >( &y ), sizeof( Y ) );
    > > out.close();


    > > ifstream in( "tmp.bin", ios_base::binary );
    > > Y y2;
    > > in.read( reinterpret_cast< char* >( &y2 ), sizeof( Y ) );


    > > cout << "y2.a=" << y2.a << endl;
    > > cout << "y2.b=" << y2.b << endl;
    > > cout << "y2.x.x=" << y2.x.x << endl;
    > > cout << "y2.x.y=" << y2.x.y << endl;
    > > }


    > Would this break if X or Y has a virtual function?


    It's broken as it stands, even without virtual functions.

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
    James Kanze, Jul 20, 2008
    #9
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. sleigh
    Replies:
    1
    Views:
    2,675
    sleigh
    Feb 12, 2004
  2. John Tiger
    Replies:
    10
    Views:
    5,564
  3. ai@work
    Replies:
    9
    Views:
    528
    Ron Natalie
    Dec 16, 2004
  4. S. Nurbe

    iostream + iostream.h

    S. Nurbe, Jan 14, 2005, in forum: C++
    Replies:
    7
    Views:
    757
    red floyd
    Jan 15, 2005
  5. red floyd
    Replies:
    3
    Views:
    526
    Dietmar Kuehl
    Mar 8, 2005
Loading...

Share This Page