Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is having a reference/ptr to std::unique_ptr<> owned object safe when the unique_ptr is in a vector?

Tags:

c++

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.

like image 937
Daniel Avatar asked Feb 03 '26 16:02

Daniel


1 Answers

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.)

like image 73
Davis Herring Avatar answered Feb 06 '26 07:02

Davis Herring



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!