0

For example if i have a class named Obj and an Obj named obj1. When I want to write in a binary file with reinterpret_cast I open that file in binary mode and then,

outstream.write( reinterpret_cast<const char *>(&obj1), sizeof(obj1) )

where outstream is a ifstream.

When i want to read from that file,

instream.read( reinterpret_cast<char *>(&obj1), sizeof(obj1) )

What happened. It read the representation of obj1 in binary and convert to obj1 or how this is working. When I write I understand that it interpret obj1 an one byte but when I read I don't understand what happens.

5gon12eder
  • 24,280
  • 5
  • 45
  • 92
  • Doing this is not working properly for complex objects. You should lookup for de-/serialization. – πάντα ῥεῖ Sep 19 '15 at 12:29
  • 1
    Unless `Ob` is a POD type, this is undefined behavior. Use `static_assert(std::is_pod::value, "not POD");` to make this sure. – 5gon12eder Sep 19 '15 at 12:30
  • i dont understand how it decode the information when it read. How can i understand in the read what happens behind scene – Otniel-Bogdan Mercea Sep 19 '15 at 12:30
  • Nothing happens behind the scene, that's exactly the point of `reinterpret_cast`! It seems you need to read up on *pointers* and different types of casts. – Marcus Müller Sep 19 '15 at 12:32
  • 1
    As we've said, for non-POD types, there is undefined behavior going on behind the scenes. And for POD types, it is just as if you `memcpy` the bits of the object to / from the file. – 5gon12eder Sep 19 '15 at 12:32
  • I see this done in C++ How to program Fifth edition and they dont say anything like you. I do this for random acces file – Otniel-Bogdan Mercea Sep 19 '15 at 12:35
  • 1
    I don't know that book so I don't want to judge it but maybe it is not a coincidence that it is not on [the list](https://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list). – 5gon12eder Sep 19 '15 at 12:41

2 Answers2

3

When you re-interpret a pointer to object as a pointer to char, you write the in-memory representation of the object itself. This includes

  • All pointers inside the object. For classes with virtual members this may include a pointer to vtable, depending on the implementation
  • All padding between members,
  • All data members, in the endianness of your hardware.

This write does not include any part of your object pointed to by pointers.

Moreover, when you read an object with pointers back into memory, the values in these pointers will be garbage. If you dereference any of it, you get undefined behavior.

This makes the technique applicable only to plain old data (POD) objects, i.e. primitives and structs/classes composed of primitives and other POD objects. In addition, the technique is not applicable when you need cross-hardware compatibility.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
2

Say, an object of class Obj takes up 4 bytes in memory.

[OBJ] = [0][1][2][3]
      = FF FF FF FF  //(for example, all bytes contain 0xFF)

A char, normally, takes up 1 byte. So when you do the reinterpret_cast your object will be treated as the 4 separate bytes (an array of characters, so to speak).

When you serialize your object in this way you will store the raw bytes 0 through 3, and your file will contain the 4 bytes 0xFF 0xFF 0xFF 0xFF. Bottom line you're copying the raw bytes into a file.

Deserialization is just as simple, you have a placeholder Obj to be read into and then the same bytes in the file will overwrite the object.


There's a caveat. This sort of serialization will only work on POD types or structures with simple data members. Like this,

struct Foo {
    int bar1;
    float bar2;
};

It won't work on things like std::vector, or std::list, etc. In general it won't work on pointers, because if you store the raw value (address) the pointer contains it will be meaningless in the next time you run your program and read this address. Your object will contain an invalid pointer after deserializing.

aslg
  • 1,966
  • 2
  • 15
  • 20
  • and if the obj is pod then in the read it uses the same "conversion" of the char bytes to convert to obj1 as it uses in the write to convert obj1 to char? – Otniel-Bogdan Mercea Sep 19 '15 at 12:58
  • 1
    There was never any conversion, which is why I said _treated_. A reinterpret cast will not convert you data. Data (bytes) is the same no matter the type you're dealing with, what changes is the way the compiler uses this data. When you reinterpret_cast something, you tell the compiler to deal with this data as if it were something else, but there is no conversion. – aslg Sep 19 '15 at 13:10
  • ok now i start to understand what you said.So i understand that instead of char would be any base type and the result will be this? – Otniel-Bogdan Mercea Sep 19 '15 at 13:12
  • If you mean that you could use any type and reinterpret cast it to char, well I mentioned that in my answer. If you mean that you could reinterpret cast to any other type besides char, you can do that too but you're at your own risk. Don't do it unless you know what you're doing. – aslg Sep 19 '15 at 13:17