Lets say we have a class that holds a pointer member to another object. If I delete that pointer in the destructor I get an error (and I understand why). My question is : is it possible to overcome that without memory leaks ?
Lets say we have a class that holds a pointer member to another object. If I delete that pointer in the destructor I get an error (and I understand why). My question is : is it possible to overcome that without memory leaks ?
The obvious solution is to use a design where this isn't possible or just forbid users of the class from doing such silly things. B should either own what it points to or not, but it is certainly possible to make it possible for either to work.
A naive implementation might look something like the following:
This is a design question. It's really about ownership. The best practice I've found is to define a single, clear owner for objects. The owner is in charge of creating the object and doing any necessary cleanup.
So the question is... who owns the A object here? Is it main()? or is it B?
If main() is owning the A object, then B should not be deleting it. It should just take a pointer and refer to the object assuming it will have the necessary lifetime.
If B is the owner, then B must do what is necessary to clean up. But knowing what is necessary means knowing how its created... so it might be better for the A to actually be created in the B class.
I wouldn't recommend keeping it how you have it now (main() allocates, but B owns)... but it could work.
Blah blah blah. Anyway, you have a few options. 3 stand out to me as the "best". One of these 3 are probably what you want, depending on what these classes are used for:
----------------------
1) B does not delete the A object, and it assumes whoever created the A object will destroy it (ie: main() will take care of it -- B is not the owner, main() is).
Pros: The A object can be allocated any which way. Multiple B's can share access to a single A. Cons: The A object must have a longer lifetime than all B objects which refer to it or else the pointer will go bad.
----------------------
2) B owns the object. By which I mean it creates it and destroys it (or accepts a passed object, but then claims ownership of that object). You can do this without allocating anything with new -- just make a normal non-new'd A object a member of the B class.
Or if you want it new'd... you can accept a pointer, but then you must ALWAYS pass a new'd pointer and can never pass a pointer to a local object like you're doing on line 31.
Pros: No lifetime issues. Since B owns the object, it can keep it alive as long as it needs it. Cons: One B = One A... multiple B's cannot share the same A. Must be mindful of how objects are created.
----------------------
3) Protected ownership with smart pointers. IE: use shared_ptr or unique_ptr to dictate ownership.
Pros: The A object can be shared by multiple B's. Cleanup is automatic. No lifetime issues.
Cons: A objects must be new'd... no local objects can be used. Must be wary of circular references if A also has a B pointer as a member.
----------------
EDIT:
cire's approach is another possibility. But I find conditional ownership to be a nightmare to maintain, so I recommend against it.
Pick an owner and run with it. Having B own the A sometimes is very error prone and confusing. It does not scale well.
cire's approach actually made me think of something interesting. I wonder if you could try to detect whether or not the pointer was dynamically allocated with something like this:
1 2 3 4 5 6 7 8
class B
{
public:
B( A*& a )
{ /* new'd - take ownership */ }
B( A*const& a )
{ /* stack allocated - do not take ownership */ }
I don't know for certain if this would work... and I know it's not perfect and the wrong version could be called in some circumstances, so I definitely am not saying you should do this. I just thought it was interesting.