I'm having a lot of trouble understanding why memcpy'ing non_copyable types is not allowed, or even if my code in the following is not allowed:
struct trivially_copyable_type
{
int member;
};
struct non_trivially_copyable_type
{
int member;
non_trivially_copyable_type() { }
non_trivially_copyable_type(const non_trivially_copyable_type& other) { }
};
int main()
{
bool result = std::is_trivially_copyable_v<trivially_copyable_type>; // True
result = std::is_trivially_copyable_v<non_trivially_copyable_type>; // False
trivially_copyable_type copyable;
void* memory = malloc(128);
memcpy(memory, ©able, sizeof(copyable));
trivially_copyable_type* p1 = (trivially_copyable_type*)memory;
p1->member = 7; // This is allowed
non_trivially_copyable_type noncopyable;
memcpy(memory, &noncopyable, sizeof(noncopyable));
non_trivially_copyable_type* p2 = (non_trivially_copyable_type*) memory;
p2->member = 7; // This is undefined or illegal?
}
If we malloc memory and access that memory through a pointer to int, as in:
int * ptr = (int*) malloc(128);
*ptr = 7; // We didn't create an int, but can treat that memory as int
In the same way:
trivially_copyable_type* ptr = (trivially_copyable_t*) malloc(128);
*ptr = 7; // Same, we didn't create a 'trivially_copyable_type object at memory, but can read and write to it
But:
non_trivially_copyable_type* ptr = (non_trivially_copyable_t*) malloc(128);
*ptr = 7; // Is whether this is legal dependent on whether the type is trivially_constructible or not?
I don't understand why or if in the earlier example where I memcpyed into the buffer would be illegal.
Consider:
Now do you see the problem? If you
memcpy
this type and then destroy the object you copied, the next call toget_member
will do the wrong thing.The class has a constructor. That means that an instance of it does not exist until it's constructed. Thou shalt not access a member of a non-existent object.