Reputation: 3614
I have a exported structure used in other submodules. Currently it is used to store data. Clients usually copy the object via memcpy
instead of copy assignment. Now I want to add a constructor on this data-store struct for convenience use.
Is it safe to add member function in exported struct on memcpy
use? Does the memory layout of the MyData
object change?
Edited:
The way to use memcpy
to copy already exist in many modules. I may not able to ask them to replace it. I just concern whether adding this new constructor may break something or not.
// MyData.h (Published to other modules)
struct MyData {
int v1;
int v2;
/*
MyData(): v1(1), v2(2) {}
*/
};
// Other Module's Client.cpp
MyData myData;
memcpy(&myData, &srcData, sizeof myData);
Upvotes: 2
Views: 69
Reputation: 131
Member function does not change memory layouts of the objects. Member functions are just like global functions, but they receives explicit "this" pointer to object from whom they are called. Here is simple example of memory layout of two objects:
struct MyData
{
int n1;
int n2;
};
struct MyData_constr
{
MyData_constr(): n1(1), n2(2) {}
int n1;
int n2;
};
int main(int argc, char* argv[])
{
MyData data;
MyData_constr data_constr;
data.n1 = 1;
data.n2 = 2;
printf("MyData size:%d\n", sizeof(MyData));
printf("MyData_constr size:%d\n", sizeof(MyData_constr));
printf("\n'data' memory dump:\n");
unsigned char* pByte = (unsigned char*) &data;
size_t i;
for(i = 0; i < sizeof(MyData); i++)
{
printf("%02X ", pByte[i]);
}
printf("\n\n'data_constr' memory dump:\n");
pByte = (unsigned char*) &data_constr;
for(i = 0; i < sizeof(MyData_constr); i++)
{
printf("%02X ", pByte[i]);
}
printf("\n-------------------------------\n");
return 0;
}
Output:
MyData size:8
MyData_constr size:8
'data' memory dump:
01 00 00 00 02 00 00 00
'data_constr' memory dump:
01 00 00 00 02 00 00 00
-------------------------------
As you can see the memory layouts and sizes of "data" and "data_constr" are binary equal.
Upvotes: 2
Reputation: 234785
This is safe although you will need to recompile all code that uses MyData
: you can't get away with not doing that.
As for using memcpy
, you can only do that if the object is trivially copyable, else the program behaviour is undefined.
If you are in any doubt then you can use std::is_trivially_copyable<MyData>::value
to check. This will be true
if, and only if, the object is trivially copyable. You could even wrap that in a static_assert
to induce a compile-time failure. This will guard you from some so-and-so changing your class in such a way that trivial copyability no longer applies (such as someone dogmatically adding a virtual destructor).
The way you currently have it, your struct
is trivially copyable, even after you've added the constructor.
Although if I were you I'd just rely on the compiler generated copy constructor and assignment operators.
Upvotes: 3