Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++11 non-owning reference/pointer to unique_ptr?

It's rather not a question "how to do it" it's rather "how to do it the right way"

I'm developing an editor in Qt where different widgets display the children and its (member) variables. Each of these widgets should hold a reference/pointer to the edited child to display and change their member variables.

The first attempt was the old ANSI C way I learned (and still kinda stuck in) with simple raw pointer to the used objects. It works fine but since the C++11 standard supports smart pointer and using them is recommended I'm trying to use them.

The problem is, I'm not quite sure what's the "best way" to use them in this case... After reading Smart Pointers: Or who owns you baby? and Which kind of pointer do I use when? and a few others I came to different conclusions:

The first is to use a*unique_ptr since the edited object is clearly the owner which creates and also deletes its children. The widgets are simply referring to the child to show or change them. The problem is how should the widgets refer to the child...

for now I'm simply still using a raw pointer I got with the get() method of the unique_ptr but this seems kinda flawed to me. I still can accidentaly call delete on the pointer and cancel the benefits of the smart pointer.

The second approach is to use a shared_ptr because many objects refer to the child and edit it. Also accidentaly deleting it in one widget would do no harm because it is still owned by other objects. The problem is they own it. When I want to delete it from the edited object I also have to signal all widgets to delete it before it is really gone. (this again seems flawed and error-prone)

I'm not really content with both ways. Is there a clean(er) way to point to the unique_ptr child of the object? Or am I missing a completely different and better approach to this problem?

like image 325
nils277 Avatar asked Aug 27 '13 01:08

nils277


People also ask

Can unique_ptr be passed by reference?

If you make a unique_ptr you can only pass by reference or move it to each class. That class cant take that reference as an own member due to unique_ptr non-copy policy. The best solution for that is share the reference as a shared_ptr.

What is non owning pointer?

The pointer that you use to perform delete is known as the owning pointer while every other pointer to that object is known as a non-owning pointer. For a pointer that refers to an object on the stack, they're all non-owning because the stack is responsible for freeing that memory.

What is the difference between shared PTR and unique_ptr?

Use unique_ptr when you want to have single ownership(Exclusive) of the resource. Only one unique_ptr can point to one resource. Since there can be one unique_ptr for single resource its not possible to copy one unique_ptr to another. A shared_ptr is a container for raw pointers.

How do you transfer ownership of a pointer that is exclusively owned?

In C++11 we can transfer the ownership of an object to another unique_ptr using std::move() . After the ownership transfer, the smart pointer that ceded the ownership becomes null and get() returns nullptr.


2 Answers

Your use case doesn't translate directly to requirements (what if someone else deletes the widget while you're editing it?) but I'll assume you don't need anything beyond a naked pointer.

The Standard Library does not provide any strict pointer-observer class. Among observer entities:

  • Nullable, mutable pointers of native type (T *)
  • Non-nullable, non-mutable references of native type (T &)
  • Non-nullable, mutable references/proxies of class type (std::reference_wrapper<T>)
  • Nullable, self-validating, mutable pointers to managed objects (std::weak_ptr<T>)

If you want a non-nullable, mutable pointer to a non-managed object, which is a fairly reasonable thing to want, you can roll your own.

But naked pointers aren't that bad. The only difference is that it can be nullptr, and that it doesn't have a nice, long, explicit name inside namespace std.

like image 91
Potatoswatter Avatar answered Sep 22 '22 15:09

Potatoswatter


You want to use a shared_ptr in place of your unique_ptr and weak_ptr's in place of your raw pointers. This will give exactly what you're after. The weak_ptr's will not interfere with the edited object's ability to delete the underlying object.

like image 44
Paul Evans Avatar answered Sep 21 '22 15:09

Paul Evans