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 <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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With