Is it possible in C++ to convert an array of chars to an object like so:
char* bytes = some bytes... MyObject obj = (MyObject)(bytes); ?
How do I have to define the cast operator?
thanks :)
You probably want to define a constructor for MyObject:
class MyObject { public: explicit MyObject(const char* bytes); ... }; MyObject::MyObject(const char* bytes) { // do whatever you want to initialize "MyObject" from the byte string } and then you can use it:
char* bytes = some bytes... MyObject obj = MyObject(bytes); // this will work MyObject obj(bytes); // so will this MyObject obj = bytes;. I'd suggest using the explicit keyword on the constructor to prevent that, it can avoid some surprising bugs.explicit is a very good idea for single-parameter constructors. I've updated my answer.std::string is not explicit and does what we expect.I can see two possibilities here. If you have data that you know represents the target type, you can use a reinterpret_cast to get them treated as an object of that type:
MyObject *obj = reinterpret_cast<MyObject *>(bytes); If you want to create an object of the specified type in the designated memory, you use the placement new operator to construct an object at the specified address:
char *bytes = whatever; MyObject *obj = new(bytes) MyObject; When you're finished using the object, you don't delete it, you directly invoke the dtor:
obj->~MyObject(); Note that for this to work, you need to ensure that (if nothing else) bytes points to data that's aligned correctly for the destination type.
MyObject * and you are just casting it back now?) then larsmans' answer is the way to go.reinterpret_cast, not a static_cast.T & memcpy to it. @T.E.D. Even if trivially copyable types - the superset of PODs guaranteed to be copyable to array of char & back & retain the same value - don't in reality emit code when allocated, the Standard still demands they have a real lifetime. This presumably means the compiler must see code that says 'Create a struct T in this piece of memory', otherwise all bets are off & UB means it can emit unsafe code or optimise the attempt away. That most compilers allow arbitrary casting doesn't make it definedIf the bytestring actually represents a valid object of type MyObject, you can get a MyObject* with
reinterpret_cast<MyObject *>(bytes) This is very unlikely to work though, unless the char* is the result of casting a pointer to a properly constructed MyObject.
char* is exempt from that rule, so only if another non-char*, non-MyObject* pointer/reference also references bytes.char * & dereferencing the result is exempt from aliasing. There's no allowance for the opposite. But as long as the pointers aren't dereferenced in the same scope - which surely there's no reason to do - then aliasing doesn't even enter into the equation. This is the same as/follows from the rule allowing 'round trip' casting of pointers & ensuring casting A * => B * => A * preserves the same A * on both sides. If one couldn't even cast the addresses of objects without aliasing, this wouldn't be possible. Aliasing only refers to dereferenced pointers ie lvalues.char* is the result of casting a pointer to a properly constructed MyObject" => +1. The Standard is very clear that only the 'round trip' form of reinterpret_cast between incompatible pointer types has defined results. Anything else is UB and hoping desperately that your compiler does what you think it should. The proper way to convert arbitrary bytes to some object - assuming it's is trivially copyable, as it must be - is to allocate an instance and memcpy() from the char buffer into it. Heck, good optimisers can render to the same code as a cast, but without invoking UBI like Jerry Coffin and larsman's answers, depending on wheather the location in question already has a constructed object in it or not.
There is one further wrinkle though. If the type of MyObject happens to qualify as a POD class, then it might be OK to just use a reintreprent cast on the pointer like larsman suggested, as no constructor is really required for the object.
I say "might" because it is remotely possible that your platform uses different representations for char * and class pointers. Most I've used don't do that though.
T, possibly with a stricter alignment than char that the compiler can't verify. I'm quite convinced it does not allow this - unless the char * in question originally came from a valid allocated T * - and that anything else is formally UB. See this comment: stackoverflow.com/questions/5436092/…char & back & keep the same value - don't in reality emit any constructor code, the Standard still demands that such objects have a well-defined lifetime. This presumably means the compiler must see code saying 'Create a struct T in this piece of memory', otherwise all bets are off & means it can emit unsafe code or optimise the attempt away. That most compilers allow arbitrary casting, as you very vaguely recommend here, doesn't make it not UB.