On the surface I like the pattern of having a container of unique_ptr's to own data. My question is, is it safe to then take pointers/references to members of such an owned object, if I know that the unique_ptr will not go out of scope?
For example I may have
auto v = std::vector<std::unique_ptr<ClassWithFooMember>>{};
v.emplace_back(std::make_unique<ClassWithFooMember>());
Can I then safely do
auto *foo_ptr = &(v.at(0)->foo);
if I know that v will outlive foo_ptr and that v will never have an item removed?
What happens if many items are added to v or if v's internal representation changes? Will the memory layouts of the ClassWithFooMember instances ever change?
Thank you.
Since the ClassWithFooMember objects “in” such a vector are allocated separately, your foo_ptr (or a pointer to the entire ClassWithFooMember object) will remain valid regardless of any operations on v so long as the (anonymous) ClassWithFooMember object exists. For instance, sorting v or causing it to reallocate would be harmless. v.erase(v.begin()) would destroy it, of course, but even then you might first have written either of
auto p=std::move(v.front());
auto *q=v.front().release();
which would let the object live on after destroying v entirely.
All this is true regardless of the container type; this is the benefit paid for by the additional memory and time overhead used for the separate allocation. Neither is it specific to std::unique_ptr (although that’s generally a good choice here for other reasons); std::vector<T*> would have the same behavior, including that it would be safe to retain a T* (or a pointer into a T) but not a T*& (or T**) referring to the vector element itself. (The corresponding unsafe thing in your case would be to hold a std::unique_ptr<ClassWithFooMember>& or std::unique_ptr<ClassWithFooMember>*, which you generally shouldn’t be doing anyway.)
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