views:

230

answers:

3

I have a C++ class(inside a dll project) whose member variables are boost::shared_ptrs to objects of other classes. Is it better to assign them inside the class constructor or have a separate init() function which does that.

I am assuming the default value of pointer to T inside boost::shared_ptr is NULL. So if I do nothing inside the constructor will boost::shared_ptr's get() return NULL before calling Init() function.

Also, what happens when there is a memory allocation problem with new in one of the assignment statement should I catch the exception(in Init) or is it good to tell the caller of this Init() to catch that exception? boost::shared_ptr a( new T);

Are there standard approaches to simulate the memory allocation exceptions inside unit tests? and see all the objects are properly de-allocated

+1  A: 

Use initializer lists for member assignments. They are the preferred (and at times the only approach).

If there is a problem during object creation, throw an exception and bail out. Or, you will need to maintain a valid flag which you'll have to check every time a member function is called just to check that the object in use is valid.

You can always catch exceptions and report them. If a deallcation fails, you ideally should not throw an exception, instead handle it in the dtor, report it and move on.

dirkgently
+1  A: 

On the first question, you should ideally use initialiser lists to ensure your pointers are valid. Not doing this means that you potentially have to check at all times whether your pointer is valid before using it; especially if you leave it up to the calling code to call init()

On the other hand, it may be that you can't do this if they can only be set by calling a pure virtual in which case you'll have to use an init() method.

On initialisation, I would think that you can either catch and rethrow or simply not catch. Either way it would be preferable, I think, for the caller to catch a memory allocation exception.

I can see why you'd want to try testing a memory allocation exception on calling init() on one of your objects. An approach here might be to substitute a stub object which always throws on a call to init()

I can't see why you'd want to check for deallocation of shared pointers (raw pointers, maybe) Surely the point with shared pointers is that while you're able to reference the shared pointer you are, by definition, sharing it so it won't yet be destructed.

Maybe you could check reference counts or have your pointed object set and (on destruction) clear a semaphore which your test could monitor. Am I missing the point somehow?

Robin Welch
Thanks for that answer Robin, I should use reference counts while unit testing. I also like the idea of creating stub
Kamal
@Kamal, the compiler will call the destructor of any initialized member if any other later initialized member throws.
Johannes Schaub - litb
+1  A: 

I have a C++ class(inside a dll project) whose member variables are boost::shared_ptrs to objects of other classes. Is it better to assign them inside the class constructor or have a separate init() function which does that.

It is usally better to do everything in the constructor.
Having an init() function that is called afterwords implies that the object is not valid after construction, so you then need to keep a state flag to indicate if init() has been called and check that flag whenever any public method are called and do somthing appropriate for an uninitialized object

I am assuming the default value of pointer to T inside boost::shared_ptr is NULL. So if I do nothing inside the constructor will boost::shared_ptr's get() return NULL before calling Init() function.

Yes: The default constructor for shared_ptr will initialize it to NULL.

Also, what happens when there is a memory allocation problem with new in one of the assignment statement should I catch the exception(in Init) or is it good to tell the caller of this Init() to catch that exception? boost::shared_ptr a( new T);

If you have a constructor: Then all members that had been constructed will be destroyed correctly (via destructor), while unitialised objects will not be touched, and the memory for the current object will be release as if never allocated (Another good reason to use the initialiser list).

If you use an init(): Then you must catch the exception clean up the object correctly and release the memory. Depending on how complex the object you may be able to do this inside the init (but it is hard to do correctly) or the caller must do it. After that you should do the same as if an exception had been thrown from the constructor (so that depends on usage).

Are there standard approaches to simulate the memory allocation exceptions inside unit tests? and see all the objects are properly de-allocated

You can use a factory object to allocate the objects.
You pass the factory object to the constructor. When you want to simulate an exception during construction just pass a mock factory that generates that appropriate exception.

Martin York