#Why doesn't recursive data member destruction solve circular dependency for shared_ptr

13 messages · Page 1 of 1 (latest)

eternal apex
#

Let's say we have

struct Foo {
  shared_ptr<Foo> data;
}
int main() {
  auto f1 = make_shared<Foo>();
  auto f2 = make_shared<Foo>();
  f1->data = f2;
  f2->data = f1;
}

This has 2 memory locations on the heap: one for f1 and one for f2. There are 4 shared pointers in total. Each shared pointer has a "count" of 2. When f1 goes out of scope, it reduces the count of it by 1. It recursively calls the destructor of its "data" which is a shared pointer copy pointing at f2 which also reduces by 1. Likewise, when f2 goes out of scope, the same thing should happen. So the counts of both objects should become 0 leading their deletion. Is there a hole in my understanding?

green whaleBOT
#

When your question is answered use !solved to mark the question as resolved.

Remember to ask specific questions, provide necessary details, and reduce your question to its simplest form. For tips on how to ask a good question run !howto ask.

astral coyote
#

it recursively calls the destructor of its "data"
It doesn't, it only does that when the last std::shared_ptr owning that object does.

#
auto s1 = std::make_shared<std::string>();
{
  auto s2 = s1; //ref count of 2
} //s2 destroyed, ref count back to 1
//destructor of std::string not called, not until s1 also dies
eternal apex
#

Destructors, C++ FAQ (isocpp.org)
According to this, "A class’s destructor (whether or not you explicitly define one) automagically invokes the destructors for member objects."

You're right in that, the actual "delete" won't happen until the count becomes 0. Because that's the way the destructor of shared_ptr would be written. But the count does reduce by 1, regardless, right?

#

whoops, not sure why the link did not appear

#

sorry, strange that discord is replacing my link with some text.

#

In my example, there are 2 Foo objects. Let's call them A and B. Each object A and B, has a common shared location where its count is being stored as a number. This count decreases by 1 each time some shared_ptr pointing to the object goes out of scope. So for both A and B, the count should eventually reach 0, at which point the actual "delete" should happen, right?

astral coyote
#

Let's call the Foo that f1 points to foo1 and the Foo that f2 points to foo2.
Going through the code:
f1 is created and points to foo1, refcount 1.
f2 is created and points to foo2, refcount 1.
f1->data points to foo2, refcount 2.
f2->data points to foo1, refcount 2.
f2 is destroyed, reducing foo2's refcount to 1. (destruction order is reverse order of definition)
f1 is destroyed, reducing foo1's refcount to 1.
The end. Since the refcount of foo1 and foo2 never reach 0 they are never deleted.

eternal apex
#

makes sense, thanks!

#

!solved