How to use smart pointers to expose internal parts of a class?

I'm trying to figure out how to adapt code written using raw pointers to use smart pointers. I have several classes where one class (let's call it Alpha) contains a list of pointers to other objects (let's call them Beta). Alpha 'owns' the Betas in the sense that it keeps track of them in a list and only it has the authority to create and destroy them. However, I want other parts of the program to be able to examine the Betas.

For example, I'd like a UI component to be able to ask Alpha for Beta[4] so that it can read it's 'name' and 'size' field for display, and also change the 'name' field in response to user input. To me this implies making the Beta's shared_ptrs so they can be returned. Alternately, I can add a method to Alpha that querys Beta's state without returning the Beta itself. I could could create a proxy object that does something similar. (The problem with the latter two aproaches is that it involves writing a lot of methods that simply pass the call along to another method. It also makes recursion difficult - what if Beta has some Gammas which in turn need to be examined?)

What's the right way to go about this? Making everything a shared_ptr seems the most straightforward. A lot of the online docs I read seem to make it look like you should avoid shared_ptrs, but I can't see any way to make this work with unique_ptr.
Last edited on
It depends on the usage of the pointer. If you want the pointer only temporary (i.e. just within a function) you can use the raw pointer using the get() function. See:

http://www.cplusplus.com/reference/memory/unique_ptr/get/


If you really want to share the pointer (i.e. two classes have a pointer to the same object) you should use shared_ptr not raw pointer.
in the later case, may return a weak_ptr
Smart pointers do not replace plain pointers -- that's a common misconception.

If it isn't desirable to transfer or share ownership, call get and pass the result.
Only work with smart pointers to share or transfer ownership -- this should be fairly uncommon, which is fortunate because it's a ripe source of errors.

What's the right way to go about this?

Maybe something like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <memory>
#include <vector>
#include <iostream>

struct beta
{ 
  int i;
};

class alpha
{
  std::vector<std::unique_ptr<beta>> data_;
  
public:
  void add(int x) { data_.push_back(std::make_unique<beta>(x)); }

  beta const* operator[](int i) const{ return data_[i].get(); }
  beta      * operator[](int i)      { return data_[i].get(); }
};

int main()
{
  alpha a;
  a.add(1);
  std::cout << a[0]->i << '\n';
}
Last edited on
Topic archived. No new replies allowed.