nkmol
nkmol

Reputation: 8091

Non owning reference to deleteable object

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.

Example

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;

Issue

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

Answers (3)

uuu777
uuu777

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

Jodocus
Jodocus

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 by std::shared_ptr. It must be converted to std::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

Dietmar K&#252;hl
Dietmar K&#252;hl

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

Related Questions