3

I'm having some difficulties trying to solve a pointer problem in C++.

Let's say I have class called MyClass. Inside this class, there is a shared pointer that points at some outside resource called MyResource. Now let's also say that within MyClass, there are a few instances of an object called MyObject. Each instance of MyObject also needs to reference MyResource. Let's assume this class doesn't do anything except contain these components I've just mentioned

class MyClass { shared_ptr<MyResource> m_p_my_resource; MyObject m_my_object1; MyObject m_my_object2; MyObject m_my_object3; } 

How I had previously (tried to) implemented this, I would create a shared pointer and give it to m_p_my_resource. I would then give m_p_my_resource to each instance of MyObject. I assumed that whenever m_p_my_resource changed to point at a new MyResource, each of MyObjects would also point at the new resource.

However, I realize what I did wasn't correct. When I would change m_p_my_resource, this would indeed be pointing at a new resource. However, each instance of MyObject would still be pointing at the original MyResource.

Now I'm trying to think of methods on how to actually implement what I was originally trying to do: be able to change m_p_my_resource and have each instance also point at the new resource.

One way to solve this is to update each instance of MyObject whenever m_p_my_resource changes. I would likely need to have a setResource method that would update m_p_my_resource and then iterate through each instance of MyObject.

An alternative solution is to have each instance of MyObject contain a pointer to a pointer of MyResource. So if each MyObject was pointing at a pointer to the resource instead of the resource itself, I could change m_p_my_resource and each object would also be able to determine the new resource.

While this second method would probably work in the class example I listed above, it's not elegant for instances of MyObject not contained within a class. As in, if I simply created a MyObject on the stack, I would rather have it point directly at the resource instead of having it point at some intermediate pointer that is pointing to the resource...

So I'm trying to determine the best method for implementing what I describe. I'm still relatively new to smart pointers and am curious if what I'm trying to do is stupid, or if there a better/obvious alternative solution.

1
  • 1
    The first solution is the proper OO way of doing it. It ensures proper encapsulation, and keeps every data structure non-incidental (assuming that MyResource is immutable). Commented Dec 18, 2016 at 0:40

2 Answers 2

3

If it is true that the lifetime of the MyObjects are identical to the lifetime of MyClass then each instance of MyObject can instead hold an reference or pointer to the shared_ptr<...> to achieve what you want.

class MyClass { public: shared_ptr<MyResource> resource; MyObject obj1 { resource }; MyObject obj2 { resource }; }; class MyObject { public: shared_ptr<MyResource>& resource; void foo() { resource->do_something(); // works transparently } } 

And you can safely change the contents of MyClass::resource:

void bar(MyClass& myClass) { myClass.resource.reset(new MyResource()); assert(myClass.resource.get() == myClass.ob1.resource.get()); assert(myClass.resource.get() == myClass.ob1.resource.get()); } 
Sign up to request clarification or add additional context in comments.

1 Comment

You assumed the lifetimes correctly. This seems like the most elegant solution. I think I've fallen victim to 'use smart pointers always and whenever' without considering the fact that they're intended to be used for heap allocated/unknown lifetime objects.
2

Double-pointers are exactly the right technique to solve your problem.

However, I'm a little confused why you would want a unique_ptr to a shared_ptr like you say in your title. You don't mention unique_ptrs anywhere in the body of your question, and it seems like what you really want is a shared_ptr<unique_ptr<MyResource>>, not a unique_ptr<shared_ptr<MyResource>>.

2 Comments

Sorry about the title, it was a classic case of writing a title and then typing out the actual problem I was trying to solve and forgetting to edit the title. Going back to your answer, isn't what you describe clunky though when MyObject is not contained within a class? In other scenarios it would make more sense to have MyObject directly contain a reference to the resource. Thoughts?
Correct, that is usually ideal. However, you asked for the ability to simultaneously change which object all instances point to, and for that you need a double pointer. The pointers don't actually have to be shared or unique, though; you can use normal pointers, but then you must manage the memory yourself.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.