we want to use pimpl idiom for certain parts of our project. These parts of the project also happen to be parts where dynamic memory allocation is forbidden and this decision is not in our control.
So what i am asking is, is there a clean and nice way of implementing pimpl idiom without dynamic memory allocation?
Edit
Here are some other limitations: Embedded platform, Standard C++98, no external libraries, no templates.
Warning: the code here only showcases the storage aspect, it is a skeleton, no dynamic aspect (construction, copy, move, destruction) has been taken into account.
I would suggest an approach using the C++0x new class
aligned_storage
, which is precisely meant for having raw storage.In the source, you then implement a check:
This way, while you'll have to change the alignment immediately (if necessary) the size will only change if the object changes too much.
And obviously, since the check is at compilation time, you just cannot miss it :)
If you do not have access to C++0x features, there are equivalents in the TR1 namespace for
aligned_storage
andalignof
and there are macros implementations ofstatic_assert
.pimpl bases on pointers and you can set them to any place where your objects are allocated. This can also be a static table of objects declared in the cpp file. The main point of pimpl is to keep the interfaces stable and hide the implementation (and its used types).
See The Fast Pimpl Idiom and The Joy of Pimpls about using a fixed allocator along with the pimpl idiom.
The point of using pimpl is to hide the implementation of your object. This includes the size of the true implementation object. However this also makes it awkward to avoid dynamic allocation - in order to reserve sufficient stack space for the object, you need to know how big the object is.
The typical solution is indeed to use dynamic allocation, and pass the responsibility for allocating sufficient space to the (hidden) implementation. However, this isn't possible in your case, so we'll need another option.
One such option is using
alloca()
. This little-known function allocates memory on the stack; the memory will be automatically freed when the function exits its scope. This is not portable C++, however many C++ implementations support it (or a variation on this idea).Note that you must allocate your pimpl'd objects using a macro;
alloca()
must be invoked to obtain the necessary memory directly from the owning function. Example:This, as you can see, makes the syntax rather awkward, but it does accomplish a pimpl analogue.
If you can hardcode the size of the object in the header, there's also the option of using a char array:
This is less pure than the above approach, as you must change the headers whenever the implementation size changes. However, it allows you to use normal syntax for initialization.
You could also implement a shadow stack - that is, a secondary stack separate from the normal C++ stack, specifically to hold pImpl'd objects. This requires very careful management, but, properly wrapped, it should work. This sort of is in the grey zone between dynamic and static allocation.
With this approach it is critical to ensure that you do NOT use the shadow stack for objects where the wrapper object is on the heap; this would violate the assumption that objects are always destroyed in reverse order of creation.
One way would be to have a char[] array in your class. Make it large enough for your Impl to fit, and in your constructor, instantiate your Impl in place in your array, with a placement new:
new (&array[0]) Impl(...)
.You should also ensure you don't have any alignment problems, probably by having your char[] array a member of an union. This:
union { char array[xxx]; int i; double d; char *p; };
for instance, will make sure the alignment of
array[0]
will be suitable for an int, double or a pointer.If you can use boost, consider
boost::optional<>
. This avoids the cost of dynamic allocation, but at the same time, your object will not be constructed until you deem necessary.