Weak_ptr and parent-child cyclic dependencies

I currently have something similar to the following:

class Parent { //just a single child... for sake of simplicity //no other class holds a shared_ptr reference to child shared_ptr<Child> _child; System * getSystem() {...} } class Child { weak_ptr<Parent> _parent; ~Child { _parent.lock()->getSystem()->blah(); } } 

The child’s destructor always fails, because when ~ Child () _parent is executed, it always expires. Is there a typical solution to this oddity?

In short, is there a way to not destroy _parent until ~ The child finishes?

+4
source share
5 answers

Since, from the moment of calling the destructor for the child user, the parent destructor has already completed (dtors for member objects starts after dtor for the containing object), even if the child had a simple pointer to the parent, the call to the parent member function will be invalid at the time point ~Child() .

You may be able to get around this with a child call to getSystem() at some earlier point and caching the result. Maybe in the Child constructor (if at that time it refers to the parent), or maybe an interface can be added so that Parent can let the child know that he needs to collect everything that he might need during the destruction of the parent element in this time.

I understand that none of them is an excellent solution (it increases the adhesion of objects) - I hope someone publishes the best option.

+1
source

Removing a circular link is preferable, but if you cannot force the child to be destroyed before the Parent completely disappears. In the destructor, I explicitly call reset () in Child. This will force it to be destroyed immediately, assuming there are no other shared_ptr for it.

Warning if Parent is actually a base class, all of its subclasses will be destroyed. Virtual function calls probably won't behave as expected.

+2
source

The first rule is weak_ptr: always check for a lock (return pointer or exception): after all, the real reason for using weak_ptr is that it does not control the life cycle of a pointed object.

+2
source

_parent.lock()->

Here you are assuming that the lock will succeed, IOW, that your weak_ptr will not expire at this time.

So you should not use weak_ptr at all, but << 24>.

Everything will be much clearer if you do not abuse weak_ptr . You will see that you have two objects that are trying to manage each other for life, and that your design needs to be fixed. (Throwing weak_ptr into the mix doesn't fix the design.)

+2
source

Just from the code you posted should work. The only thing that removes _child is the parent class.

So, there are two possibilities: firstly, something else has a reference to the _child pointer and saves it ref count alive, and then the parent is destroyed. Then, in the end, everything that holds the child back is also destroyed, killing the child later.

Scenario 2 is that the call to getSystem depends on some other participants that you do not show, and they are deleted before _child shared_ptr.

0
source

Source: https://habr.com/ru/post/1332573/


All Articles