Reputation: 25
I have three classes: A, B, C
in class A there is a vector<vector<B>>
in class C there is a vector<unique_ptr<B>>
the ptrs in the C vector simply points at the elements of the 2d vector in class A.
I only want a reference to these elements and I don't want to have to create new memory with these pointers (not sure if that is what the unique_ptrs are doing).
In this case, would I be better off just using raw pointers?
EDIT: I don't want the objects I'm pointing at to be deleted when the vector is deleted (when the ptrs go out of scope)
Upvotes: 0
Views: 328
Reputation: 51920
The lifetime if the B
objects is managed by the vector in A
. That means there is no need to wrap a unique_ptr
around them. In fact, that's an error if your unique_ptr
s are not created using a no-op deleter; in that case, they will delete the objects, and then the vector will delete them again.
Since C
just needs to observe the objects, you can use raw pointers. Non-owning raw pointers (meaning pointers you never call delete
on) are fine.
However, this kind of long-term raw pointer can be hard to reason about. Are the objects pointed to still valid? How do you know? You might want to instead add an API to A
that provides access to the objects and only access them in C
when needed, without storing any pointers to them.
Upvotes: 0
Reputation: 155674
You can't (well, shouldn't unless you love corrupting all the things) use unique_ptr
to refer to objects not allocated via new
(or implicitly via std::make_unique
).
Using raw pointers isn't a particularly good idea either unless you fully initialize A
's 2D vector
before initializing C
's, and then never resize it after that; resizing would invalidate your pointers, causing undefined behavior should you attempt to read from them.
I'd recommend 1 of 2 options, depending on what works best in your scenario:
Use a vector<vector<std::shared_ptr<B>>>
in A
(populating it with types allocated via std::make_shared
) and make C
's vector
either vector<std::shared_ptr<B>>
(if deleting from A
should not affect C
and there aren't reference cycles involved) or vector<std::weak_ptr<B>>
(if deleting from A
should remove the reference in C
)
If C
points to a logical index in A
(where changing the value in A
's vector
should change what is seen through C
), change C
to hold:
a. A reference to A
's vector
(or A
itself)
b. A vector<std::pair<size_t, size_t>>
where each pair
defines the indices to use to look up the associated value in A
's vector
.
Option 2 means A
doesn't have to change much, if at all (aside from making sure C
can see its vector
); the vector
remains value based, so using a value in it remains only two random access indirections, not the 3-4 required when using shared_ptr
(std::make_shared
means it's effectively 3, where manually calling new
and std::shared_ptr
is 4).
Upvotes: 1