Jump to content

  • Log In with Google      Sign In   
  • Create Account

How to allocate objects


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
2 replies to this topic

#1 larspensjo   Members   -  Reputation: 1538

Like
0Likes
Like

Posted 12 October 2012 - 07:48 AM

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):
  • 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.
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).
Current project: Ephenation.
Sharing OpenGL experiences: http://ephenationopengl.blogspot.com/

Sponsor:

#2 wqking   Members   -  Reputation: 756

Like
0Likes
Like

Posted 12 October 2012 - 08:35 AM

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.

http://www.cpgf.org/
cpgf library -- free C++ open source library for reflection, serialization, script binding, callbacks, and meta data for OpenGL Box2D, SFML and Irrlicht.
v1.5.5 was released. Now supports tween and timeline for ease animation.


#3 Codarki   Members   -  Reputation: 462

Like
2Likes
Like

Posted 12 October 2012 - 10:09 AM

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




Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS