Reputation: 8091
What would the best practice to hold a non owning reference to a object, that can be deleted?
The first part is fairly simple, I simply using the stupid-smart pointer: observer_ptr
. However, the last part makes it somewhat more difficult.
Having this setup, to illustrate the need of my vector unique ptr
class Object
{
};
class Derrived : public Object
{
};
With the implementation of
vector<nonstd::observer_ptr<Object>> _observers;
vector<unique_ptr<Object>> _objects;
auto t = make_unique<Derrived>();
_observers.push_back(nonstd::make_observer(t.get()));
_objects.push_back(move(t));
// Same objects
cout << (_observers.at(0).get() == _objects.at(0).get()) << endl;
Now at any time, somewhere, one of the objects in _objects
might be deleted.
I will simply illustrate this by deleting the first object in the vector:
_objects.erase(_objects.begin());
This will result in the _objects
vector is empty. However, the _observers
vector now points to a freed memory space.
Of course, I can simply delete the observer from _observers
, but imagine having such observing references in different parts of my program.
Would there be any cleaner solution for this, and it this the right way to observe different objects?
Please let me know if the example at hand does not illustrate the problem (or any problem for that matter) that I described.
Upvotes: 0
Views: 354
Reputation: 891
Today there is no way to make non-owning relationship to be enforced by compiler: 1. weak_ptr could be converted to shared_ptr 2. Everything else could be deleted. 3. Wrappers around weak_ptr that would be non convertible to shared_ptr would not work also: once reference to an object is retrieved it could be deleted too.
Upvotes: 0
Reputation: 7601
As stated in the comments, this is a typical use-case for std::weak_ptr
:
std::weak_ptr
is a smart pointer that holds a non-owning ("weak") reference to an object that is managed bystd::shared_ptr
. It must be converted tostd::shared_ptr
in order to access the referenced object.
Example:
vector<shared_ptr<Object>> objects;
objects.push_back(make_shared<Derived>());
weak_ptr<Object> ptr{ objects.back() };
auto sh_ptr = ptr.lock(); // increase reference count if object is still alive
if(sh_ptr) { // if object was not deleted yet
sh_ptr->doStuff(); // safely access the object, as this thread holds a valid reference
}
Upvotes: 2
Reputation: 153965
Your use-case sounds like a std::weak_ptr<Object>
would be suitable non-owning representation. Of course, for a std::weak_ptr<T>
the owning representation is std::shared_ptr<T>
. However, since you’ll need to “pin” the object before you could access a std::weak_ptr<T>
you’d have more than one owner anyway while accessing the pointer.
Upvotes: 4