Create a non-owning shared_ptr?
Asked Answered
P

3

6

I am pretty new to C++11 and am now working on improving my C++ skills by trying to avoid direct usage of pointers. I am trying to write a sprite manager that keeps track of previously loaded sprites and frees unused ones. I am trying to use shared_ptr (pointer to the bitmap) for this, but the manager also has to keep a shared_ptr to create the sprites with - so the reference count doesn't drop to 0. Can I somehow declare the "parent" shared_ptr in my manager non-owning so it doesn't count as a reference (and still create owning copies of that shared_ptr)?

Plenum answered 30/7, 2012 at 12:55 Comment(0)
T
11

Use a weak_ptr. That will solve your problem. You won't need to free them as they will be automatically freed. Use a lock on the weak_ptr to get an actual shared_ptr.

The use_count will also give you the current number of references.

Traverse answered 30/7, 2012 at 12:56 Comment(2)
So my manager would hold a weak_ptr that's created upon creating the first shared_ptr, and then later creates more shared_ptrs from that weak_ptr? Sounds good.Plenum
Yes. That is correct. However if the first shared_ptr goes out of scope you would need to recreate it.Traverse
O
3

shared_ptr are made to be owning. If you want a non-owning pointer at some part of your prgram use weak_ptr like so:

std::shared_ptr<Object> sp(new Object);
std::weak_ptr<Object>(sp);
Oscine answered 30/7, 2012 at 13:0 Comment(0)
P
1

You're trying to do a kind of "backseat driver" style of memory management; you want to use shared-ptr, but you also want to control when shared_ptr frees resources!

There are a couple of obvious things you could do here.

  1. Just use shared_ptr and don't bother with any sort of memory management or resource ownership in your sprite manager class. Trust shared_ptr to do its job. If you need to know when a resource is destroyed, you can always use the observer pattern or the like, and have your resource class message the manager when it is destroyed. Of course, this means you can't ask your sprite manager to provide additional references to an existing sprite, which isn't so great.

  2. Write your own smart pointer. It isn't necessarily trivial, but writing a resource-specific reference-counting smart pointer isn't rocket science (its a hell of a lot simpler than writing something like shared_ptr, for example). The manager can then terminate resources when there's only a single reference to them remaining (eg. its own reference).

  3. Everyone else has already mentioned weak_ptr. Has all of the benefits of (1), only you can create additional shared_ptr instances referencing the same underlying resource.

You might also want to consider resource usage patterns, and the cost of loading resources. You may not necessarily want to destroy a resource as soon as your application stops referencing it; if it is requested again a second later, it might take some time to reload it. Lazily freeing resources when they've gone unused for a little while might be a better approach. Just a thought.

Poseur answered 30/7, 2012 at 13:9 Comment(1)
Thanks for the tip. I'm writing a game that's organized into levels - the idea is to load the next level and then destroy the previous one so shared sprites are kept alive. I'm not sure yet if I'm going to allow resource loading within one level at all, but even if I do it's going to be a rather rare occurrence.Plenum

© 2022 - 2024 — McMap. All rights reserved.