|
|
|
|
|
by worstspotgain
703 days ago
|
|
Let me preface by noting that I don't necessarily disagree with any part of what you wrote. However, there are design patterns that exceed the guardrails you're thinking of, and those are the patterns that benefit the most from shared_ptr. Typically, they involve fine- to medium-grained objects, particularly those that have dynamic state (meaning by-value copies are not an option.) An example might be a FlightAware-like system where each plane has a dynamically-updated position: class Plane { ... void UpdatePosition(const Pos &); Pos GetPosition() const; };
using PlanePtr = std::shared_ptr<Plane>;
using PlaneVec = std::vector<PlanePtr>;
class Updater { ... PlaneVec mPlanes; };
class View { ... PlaneVec mPlanes; };
Updater routinely calls UpdatePosition(), whereas View only calls const methods on Plane such as GetPosition(). There can be a View for, say, Delta flights and one for United. Let's simplify by assuming that planes are in the sky forever and don't get added or removed.Destructing Updater doesn't affect Views and vice-versa. Everything is automatically thread-safe as long as the Pos accesses inside each Plane are thread-safe. The key here is that Plane is fine-grained enough and inconsequential enough for lazy ownership to be ideal. |
|
If planes are around forever, wouldn't you be better off interning them? e.g. having a single global std::vector<Plane> (or std::array<Plane, N>) and passing around offsets in that array? And your PlaneVec would just be a glorified std::vector<size_t> (or int)? I don't see any value in maintaining a reference count if you're never intending to clean up these objects.
(The argument for using int here would be if you always have fewer than 2 billion planes, and so you can store a PlaneVec in less space. size_t is indistinguishable from Plane* in this context; you have the same amount of indirections either way.)
As I said, shared ownership has its uses, but most instances I've seen could have been replaced with a different model and would have been less painful to debug memory leaks and use-after-free.