How to allocate objects

Started by
1 comment, last by Codarki 11 years, 6 months ago
Looking for advice or ideas on how to best allocate objects. The preconditions are:

  • 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.

There are a couple of ways to do this (and possible more):

  1. M allocates (using new) a pointer to the O instance. It has to be deleted with the destruction of M.
  2. M uses std::unique_ptr<> to the O instance. A call to "new" is still needed, but destruction will be automated.
  3. The O instance is declared as a member of M.

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).
[size=2]Current project: Ephenation.
[size=2]Sharing OpenGL experiences: http://ephenationopengl.blogspot.com/
Advertisement
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.

https://www.kbasm.com -- My personal website

https://github.com/wqking/eventpp  eventpp -- C++ library for event dispatcher and callback list

https://github.com/cpgf/cpgf  cpgf library -- free C++ open source library for reflection, serialization, script binding, callbacks, and meta data for OpenGL Box2D, SFML and Irrlicht.


  1. M allocates (using new) a pointer to the O instance. It has to be deleted with the destruction of M.
  2. M uses std::unique_ptr<> to the O instance. A call to "new" is still needed, but destruction will be automated.
  3. The O instance is declared as a member of M.

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".


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.


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).

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.

This topic is closed to new replies.

Advertisement