Something is handling both list [1], that something could own the object, or maybe something external to that. Giving ownership of the object to both list is a design error [2].
[1] e.g. if the two list are an implementation detail of a data structure, the data-structure itself could own the objects in the lists.
[2] Do non-deterministic garbage collectors that handle cycles allow you to have a resource with multiple owners? Yes. Should you do it? No, god, please don't.
Imagine you have an arbitrary long lived connected cyclic graph that can be incrementally updated from multiple short lived worker threads. With a GC, this is a no brainer: just put the objects in the graph. No workarounds, no extra tracking.
Without a GC, on removing a node, you have to walk to essentially do a mark/sweep of the graph to find dead nodes that were connected through the node you removed.
Removing an object is just as easy as removing an element from the vector. (If you test the weak_ptrs on use, that's actually the only thing you would need to do).
And I know it for the .NET GC, they tried a reference counting GC as alternative to a collecting GC and it performed worse and comes with the cycle trouble.
Reference counting works fine as long as you don't have cycles, of course.
Of course, not having to implement the garbage collector yourself is a benefit.
User decides to view a couple of orders. Orders reference products. Those products are managed by something (e.g. an unordered_map of shared_ptr). The order can check, is my product there? If so, i'll copy the shared_ptr to it. Otherwise, I create a shared_ptr for a product and store a copy in the manager. When the order's destructor is triggered, you check the count of the shared_ptr. If it is 2 (i.e. the order and the manager), the order removes the shared_ptr.
[1] Single ownership is the key concept, not reference counting which is just an implementation detail.
https://news.ycombinator.com/item?id=7315575
(Don't want to duplicate the comment once again.)
I don't think I asked for that but correct me if I did (maybe I'm just not understanding your point).
Anyways, could you elaborate why shared_ptr, unique_ptr, and weak_ptr don't work in that case?
shared_ptr works fine for my example. Shared immutable state is a case where reference counting works extremely well, since immutability implies no cycles.