Fast approach to wrapping data in a struct/class
EDIT: The main intent is to allow manipulating underlying data as part of an encapsulated struct as opposed to direct data manipulation.
Which of the following approaches is recommended when it comes to wrapping some data inside a struct:
Keep a pointer to the data within the struct:
new s(buf)
, which stores buf in a local field (s->buf = buf
)reinterpret_cast-ing a memory address to a struct:
reinterpret_cast<s*>(buf)
Use the
new
operator against the memory address where the data is located:new(buf) s;
Here is a sample program for these approaches:
#include <开发者_如何学C;iostream>
using namespace std;
struct s {
int* i;
s(int* buf) : i(buf) {}
int getValue() { return *i * 2; }
};
struct s2 {
int i;
int getValue() { return i * 2; }
};
int main() {
int buf = 10;
s a(&buf);
cout << "value: " << a.getValue() << ", size: " << sizeof(a) << ", address: " << &a << ", buf-address: " << &buf << endl;
s2* a2 = new(&buf) s2;
cout << "value: " << a2->getValue() << ", size: " << sizeof(*a2) << ", address: " << a2 << ", buf-address: " << &buf << endl;
s2* a3 = reinterpret_cast<s2*>(&buf);
cout << "value: " << a3->getValue() << ", size: " << sizeof(*a3) << ", address: " << a3 << ", buf-address: " << &buf << endl;
}
And the output:
value: 20, size: 4, address: 0027F958, buf-address: 0027F964
value: 20, size: 4, address: 0027F964, buf-address: 0027F964
value: 20, size: 4, address: 0027F964, buf-address: 0027F964
Both size & time are important. Also, maintainability is important, e.g. someone might add by mistake a virtual function to s2
(which will mess up the data alignment).
Thanks!
None of those are even remotely good ideas, although the first one is passable with some modifications. reinterpret_cast
doesn't work the way you think it does, and I'm not sure what exactly you're trying to achieve with placement new. Store a smart pointer of some sort in the first one to avoid the obvious issues with lifetime, and the first option isn't bad.
There is a fourth option: just store the data in a struct, and provide whatever encapsulated access you desire.
struct data {
data(int i_) : i(i_) { }
int i;
};
struct s {
s(int i_) : i(i_) { }
data i;
};
Rereading your question, it appears as though maybe your intent is for this struct to be an internal detail of some larger object. In that case, the lifetime issues with the first solution are likely taken care of, so storing a raw pointer is less of a bad idea. Absent additional details, though, I still recommend the fourth option.
Placement new will still call the constructor, wiping out anything that's in the buffer already if such a constructor exists (or is created unknowingly in the future) so I don't think that's a safe option. reinterpret_cast
is undefined behavior even though it may appear to work for you. Storing a local pointer seems to be the best option although you've only given a very tiny inkling of what you're trying to do.
If you're attempting serialization here, remember important issues like sizeof(int)
and endianness.
Using reinterpret_cast with anything other than char* is an undefined behavior. So 2/ is obviously out.
1 and 3 are OK but 1/ is the most straightforward.
You may prefer to encasulate data, you may want to use a (void*) pointer to a struct or class, these allows type encapsulation, and allow to extend the data in your struct, in next versions of your code:
struct HiddenCode{
int Field1;
char Field2;
};
void transferData(void* anyptr)
{
// this method "knows" that "anyptr" is a "HiddenCode*"
HiddenCode* MyHiddenCode = (void*) anyptr;
// do something else
}
void main()
{
HiddenCode* MyHiddenCode = new HiddenCode();
MyHiddenCode->Field1 = 5;
MyHiddenCode->Field2 = '1';
void* anyptr = (void*)MyHiddenCode;
transferData(anyptr);
}
Cheers.
精彩评论