Sign in to follow this  

How to allocate objects

This topic is 1923 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Looking for advice or ideas on how to best allocate objects. The preconditions are:[list]
[*]There is a master class M that need access to an object (instance) of O.
[*]M is the only one that needs the access.
[*]O shall be allocated with M, and destroyed with M.
[*]O is not very big and has a trivial constructor that will never fail.
[*]O and M are different enough so as not to warrant a merge.
[/list]
There are a couple of ways to do this (and possible more):[list=1]
[*]M allocates (using new) a pointer to the O instance. It has to be deleted with the destruction of M.
[*]M uses std::unique_ptr<> to the O instance. A call to "new" is still needed, but destruction will be automated.
[*]The O instance is declared as a member of M.
[/list]
I suppose alternative 2 is usually to prefer before alternative 1. But the choice between 2 and 3 is harder.

Instinctively, I prefer option 3. That way, I don't need to bother with dynamic allocation. But the drawback is that the declaration of O has to go into the header file of M (whereas only a forward declaration is needed for alternative 1 and 2). If there is a complex data hierarchy, it can all end up (indirectly) with a lot of includes in the top-most type. And that does not "feel right".

I usually follow the pattern to have a trivial constructor that only makes sure everything is cleared, and then a Init-function that do the real initiation (which can also return a failure).

Share this post


Link to post
Share on other sites
I can't see the reason that how hard to decide between 2 and 3.
Is O a part of M? If it is, go with 3, otherwise, go with 2.
With 2 you can also allocate O on the stack, so no heap is needed.

Also with 2, you don't need to forward declare O, because you don't need O in the header of M, you can only include O in the cpp of M.

Share this post


Link to post
Share on other sites
[quote name='larspensjo' timestamp='1350049701' post='4989459'][list=1]
[*]M allocates (using new) a pointer to the O instance. It has to be deleted with the destruction of M.
[*]M uses std::unique_ptr<> to the O instance. A call to "new" is still needed, but destruction will be automated.
[*]The O instance is declared as a member of M.
[/list]
I suppose alternative 2 is usually to prefer before alternative 1. But the choice between 2 and 3 is harder.

Instinctively, I prefer option 3. That way, I don't need to bother with dynamic allocation. But the drawback is that the declaration of O has to go into the header file of M (whereas only a forward declaration is needed for alternative 1 and 2). If there is a complex data hierarchy, it can all end up (indirectly) with a lot of includes in the top-most type. And that does not "feel right".
[/quote]

1. You must either disable or implement copy and move semantics for M.
2. I usually go with this initially.
3. If M is implemented using pimpl, then header include is not needed. O instance can be a member of implementation of M. (efficient as 1 and 2, plus other benefits)

I usually go with plain members for low-level classes, pimpl for high-level classes, and unique_ptr<> for all others requiring heap allocation.

[quote name='larspensjo' timestamp='1350049701' post='4989459']
I usually follow the pattern to have a trivial constructor that only makes sure everything is cleared, and then a Init-function that do the real initiation (which can also return a failure).
[/quote]
I usually follow the pattern to have a trivial constructor that only initializes members, and separate the building of the object outside of the class (to either builder or free function). The building process can fail returning empty or throwing exception, or by using builder object you can pass it around, and create more elaborate construction error reporting. IMO this has many other advantages, such as simplicity and reduced compilation times.

Share this post


Link to post
Share on other sites
Sign in to follow this