I want to store polymorphic objects with variable size that derive from the Base
class on the free store.
I also want to store a bool
value in the same memory block, right before the memory reserved for the derived object.
/*
Desired memory layout for storage of one object:
base address
v
| | |
| bool | . . . . . variable size . . . . . |
| | |
^ ^
object address end address
*/
The first thing I tried was creating a struct
with a bool
member and an aligned storage of a template-passed parameter std::size_t
size.
I've tried using offsetof
and reinterpret_cast
like in one of my previous questions , but the program always crashed and I wasn't able to debug the error.
Therefore, I tried using std::malloc
and std::free
, and the program works as expected. However I'm now lacking C++ new
/ delete
safety and I don't have any kind of alignment.
I would really like to find a way to re-implement the code below using std::aligned_storage
or something that assures me the code will work on any platform and will be standard-compliant.
I want to store the additional bool
in memory before the actual object.
struct Base { virtual ~Base() { } };
struct Der1 : Base { char c[100]; };
struct Der2 : Base { char c[200]; };
template<typename TBase> struct LocalRecycler
{
// Allocated, but unused pointers, that can be recycled
std::vector<void*> recyclable;
// Upon destruction, free all allocated memory
// No need to call the destructors, as I'm 100% sure recyclable
// pointers alredy destroyed their inner object
~LocalRecycler()
{
for(auto p : recyclable) free(p);
}
// I'm omitting variadic template parameters for generic construction,
// as they are not relevant to the question
template<typename T> T* create()
{
void* objAddress;
// If we have some space that is already allocated, use it
// Otherwise, allocate new space
if(!recyclable.empty())
{
objAddress = recyclable.back();
recyclable.pop_back();
}
else
{
// Note how I'm not taking into account alignment here
// That's one reason why I would like to avoid using `std::malloc`
objAddress = std::malloc(sizeof(bool) + sizeof(T));
}
// Construct a `bool` at the beginning of the allocated memory block
// Construct a `T' after the bool
new (objAddress + 0) bool{true};
new (objAddress + sizeof(bool)) T{};
return reinterpret_cast<T*>(objAddress + sizeof(bool));
}
void recycle(void* mPtr)
{
// Destroy the inner object
TBase* basePtr{reinterpret_cast<TBase*>(mPtr + sizeof(bool))};
basePtr->TBase::~TBase();
// The memory block can now be reused
recyclable.emplace_back(mPtr);
}
};
The above code seems to work properly in my program.
What I am asking is: how can I "convert" the above C-style code to modern C++11/C++14 code, also taking care of alignment?
It seems that creating a class like the following do the job:
template <typename T>
struct ClassWithBool
{
bool b;
T t;
};
And then you may use std::allocator
to allocate/destroy the object.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.