I have two std containers. Both of them with pointers to the same data structure. The first containing all the data and the second one containing only some of the same data. Should I use shared_ptr
or weak_ptr
on the second container?
Firstly, when I read the reference I thought about using unique_ptr
on the first collection. My first collection contains all the data and it's the only one that "owns". Meaning that if the data is not there it should be deleted. But then when I try to create the second collection I didn't know what to do. I created a unique pointer but now I need another pointer to the same element destroying uniqueness, but in fact the real owner was not the new pointer. So I understood (I hope I'm not wrong) that the uniqueness is on the way of reaching elements and not (e.g.) the possibility of delete it. So, shared_ptr
. I have them on my first collection. But now the second one comes up, I thought to use shared_ptr
here too. The ways to access the same data could be both, so the owners are two. But in my case the data is always deleted from the second before. And if I use a weak_ptr
, the number of owners will not increase. In both cases the element will be deleted when the first collection wants. At the end I'm using shared_ptr
because with weak_ptr
I need to lock()
every pointer in every line of code, making it less readable. But what should I really use?
By using a weak_ptr , you can create a shared_ptr that joins to an existing set of related instances, but only if the underlying memory resource is still valid. A weak_ptr itself does not participate in the reference counting, and therefore, it cannot prevent the reference count from going to zero.
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.
You should not use smart pointers when you want to pass a reference to an object to a function and the function does not destroy or prevents the destruction of the object. In other words, if the function does not participate in the lifecycle of the passed object. For example: #include <iostream>
Smart pointers should be preferred over raw pointers. If you feel you need to use pointers (first consider if you really do), you would normally want to use a smart pointer as this can alleviate many of the problems with raw pointers, mainly forgetting to delete the object and leaking memory.
It doesn't sound like you need std::shared_ptr
because your data is owned in one place.
I would recommend using std::unique_ptr
in the owning container and then simply put the raw pointers in the second and subsequent containers.
This works because you will never delete the raw pointers but the data they point to is still managed by a smart pointer and so will be released when you no longer need it.
Despite some bad press, raw pointers are perfectly respectable when used as non owning accessors to data that is owned by some other entity that will delete it at the appropriate time.
You haven't given a critical piece of information, which is whether you can guarantee that the two collections have the same lifetime or not. If you can guarantee that both collections have the same lifetime, then using unique_ptr for the collection that owns everything and raw pointers for the other (as @Galik suggests) is ideal.
If you cannot guarantee that the two lifetimes match, then whether you select shared_ptr's for both or shared_ptr for the first and weak for the second depends on when you want the objects to be destroyed. It sounds like only the first collection is a true owner, so you'd want weak pointers.
However, I'd heavily recommend that you stick with the first approach. It's much cleaner to avoid shared_ptr and weak_ptr. The danger is that if your two collections have different lifetimes, the first collection can be destroyed before the second (just a single misplaced brace), and then when the second collection tries to access, it has dangling pointers. You can of course simply be careful with your variables, but guaranteeing that two independent local variables consistently have the same lifetime is surprisingly easy to mess up.
If you make both collections elements of the same class, you guarantee that they get constructed and destructed at the same time. The exact details of what that class should look like and which code should go where depends on the details of your problem, of course. But even something as simple (albeit bizarre) as making them both the only members (and public) of the same struct is better than using two local variables.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With