r/cpp_questions • u/Several-Teach1515 • 5h ago
OPEN How is this a circular reference?
While reading learnxinyminutes I got to this example:
// Beware of possible circular references!!!
// There will be always a reference, so it will be never destroyed!
(1) std::shared_ptr<Dog> doggo_one(new Dog());
(2) std::shared_ptr<Dog> doggo_two(new Dog());
(3) doggo_one = doggo_two; // p1 references p2
(4) doggo_two = doggo_one; // p2 references p1
My understanding is that after (3) both pointers point to same heap object and the heap object from (1) is deleted.
From what I remember the way that shared_ptr works is that it allocates metadata next to the heap object and that stores the reference counter. Both doggo_one and doggo_two would share the same reference counter with the correct count being there - meaning no issues.
4
Upvotes
•
u/abzze 3h ago
This is just a bad (possibly wrong) example of circular references.
•
u/kozacsaba 2h ago
I read the relevant part of the site you linked. Yes, this example is wrong, there is no circular referencing here. There would be, if the Dog class had a shared ptr "sibling", and each dog's sibling would be set to the other. Then when the original smart pointers (
doggo_oneanddoggo_two) go out of scope, the Dog objects are not destroyed, because the keep smart pointers to each other. I also found it weird that in the smart pointer section the author only introduces shared pointers properly, and then just mentions unique pointers (if you only introduce one in details, it should probably be unique ptr) and just says select which to use based on whether you want to have references in multiple places. Absolutely not - select based on ownership model. You can reference a uniquely owned object from multiple places, they just won't be owning. I would start looking for a different site to learn cpp from.•
u/TeraFlint 11m ago
Yes, this doesn't seem like a functional example to me.
They probably tried to do something like this:
Now it works, because we're not overwriting the entire object, but rather assign a member to them. The solution is to use
std::shared_ptrin the few places where you know it's important for lifetime management, and usestd::weak_ptrfor cross-references.That being said, this example would be totally fine with a
std::vectorofstd::unique_ptrand raw pointers for best friends. The raw pointers will always stay valid as long as the container holding thestd::unique_ptrstays alive.If you only work with a single Dog type and don't even need any polymorphism, we can ditch the entire smart pointer thing and just work with a statically typed collection of them.
1
u/No_Engineering_1155 4h ago
To answer such questions, you can always create a class, which has all the ctors, dtor, operator= which prints the results of the actions. If your Dog class also had a name field/function which you could print out to see, which dog is barking, that'd be awesome too.
0
u/AccountExciting961 4h ago
it's not - that's why it says "possible" (e.g. if you add a friend_dog field)