Working with ptr to items in containers, thoughts?

I recently see my self often trying to take pointers from non dynamic allocated objects from smaller containers, and it seems to work fine.

for example
1
2
3
4
5
6
7
std::list<Node> nodes;

Node* AddNode()
{
   nodes.push_back(Node());
   return &nodes.back();
}


(container outlives the returned ptr)

obviously std::vector doesn't work due to the reallocation issues.
and std::vector<smartptr<Node>> seems to contain unecessary allocations.

I wonder if anything is wrong with this, (maybe some details from std::list i'm missing that doesn't gurantee no reallocations) and I probably should back out and simply go with smartptrs in this case?

Let me know your thoughts!

Thanks

Last edited on
"The standard containers are free to reallocate their objects, but they won't touch referenced stuff."
What I've read somewhere in the forum, I'm not 100% sure how valid this is in this case by just using push_back(..)
Last edited on
deleted
Last edited on
Obviously std::vector doesn't work due to the reallocation issues.

These particular restrictions are called iterator invalidation rules. Note that reallocations can't just occur whenever - there are some guarantees made. cppreference has this handy table to summarize:
https://en.cppreference.com/w/cpp/container#Iterator_invalidation

std::vector<smartptr<Node>> seems to contain unnecessary allocations.

What is smartptr? If it is std::shared_ptr, std::make_shared can be used to eliminate unnecessary allocations.
Last edited on
oh, I've never seen this link on the cpp refernce website, thanks !

By reading it, this would mean it is actually safe, and wouldn't invalidate my ptr, and the statement about the free allocation for objects doesn't apply here?


What is smartptr? If it is std::shared_ptr, [quote]std::make_shared can be used to eliminate unnecessary allocations.


std::make_shared simply creates a shared_ptr and therefore is again an dynamic allocation.
by smartptr i mean any of the smartpointers (std::unique or std::shared) and with unnecessary i mean it dynamically allocates memory for the vector and also dynamically allocates memory for the smartpointer.
Last edited on
By reading it, this would mean it is actually safe, and wouldn't invalidate my ptr, and the statement about the free allocation for objects doesn't apply here?

Yes, it'd be fine to use std::list subject to the rules in that table.

std::vector::push_back invalidates iterators, references, and pointers to its elements if and only if the vector's capacity is modified by the call. If you used a vector instead, it wouldn't be safe to push_back into it unless you could guarantee that its capacity would not change (by reserving enough space ahead of time).

std::make_shared simply creates a shared_ptr and therefore is again an dynamic allocation.
std::make_shared commonly eliminates an allocation by merging the allocation of internal reference counters with that of storage for the pointed-to object. But yes, std::shared_ptr usually needs to allocate at least once.

std::unique_ptr has no shared control block and won't require additional allocations. In the common case where its deleter is an empty class, std::unique_ptr is generally the same size (through empty-base optimization) as the raw pointer it represents.

std::vector<smartptr<Node>> seems to contain unnecessary allocations.

If you store smart pointers you must have space for the smart pointer itself as well as the object the pointer owns. Doing this does prevent issues with iterator invalidation.
Last edited on
Topic archived. No new replies allowed.