This is more of a 'what if' question than a practical one. Assume that I allocate some polymorphic objects in such a way that the allocator always reserves enough room for the largest object. I want to know if you can use memcpy
to change the polymorphic type of one object to another.
Out of my head; not tested:
class Animal {
virtual ~Animal() {}
};
struct Cat : public Animal {
int lives;
};
struct Dog : public Animal {
size_t bark_count;
};
Dog* dog = malloc(std::max(sizeof(Dog), sizeof(Cat)));
new (dog) Dog(0);
Cat* cat = malloc(std::max(sizeof(Dog), sizeof(Cat)));
new (cat) Cat(9);
// Make cat a dog. Is this possible?
memcpy(reinterpret_cast<char*>(cat), reinterpret_cast<char*>(dog), sizeof(Dog));
I'm assuming that due to the question When is a type in c++11 allowed to be memcpyed?, this is invalid behavior. However, I'm not 100% sure, either.
Context: I'm writing a type checker and need to 'rewrite' types as more information comes available. I thought about refactoring the Type
class to a union type but it will require a considerable amount of work. Other approaches are very much welcome.
I'm assuming that due to the question When is a type in c++11 allowed to be memcpyed?, this is invalid behavior. However, I'm not 100% sure, either.
Exactly.
Your class is not trivially-copyable due to having a non-trivial destructor because it is virtual
.
Therefore, copying the object representation with memcpy
isn't possible at all. Even worse, the types are also not implicit-lifetime and therefore memcpy
won't create any Dog
object in the cat
storage at all. The behavior will be undefined, at a minimum if you actually use the destination buffer as if it contained the Dog
object. The memcpy
itself may be ok with some nuances to how exactly you have written the example.
Writing object representation byte-by-byte through character-like pointers isn't covered by the standard currently either way. memcpy
is just specified as a "magical" function that somehow copies underlying bytes of an object in such a way that if all underlying bytes of a trivially-copyable object were copied into an object of the same type (which may be implicitly-created by memcpy
), that then the destination object will hold the same value as the source object.
reinterpret_cast<char*>
is pointless btw. memcpy
wants a void*
and the conversion to it is implicit.