I need to know when i insert element into this container does previous items preserve their addresses or after some time this container reallocates/copies everything into another memory locations?
How does it store elements?
> Moreover, inserting an element invalidates no iterators, and removing an element
> invalidates only those iterators which point at the removed element.
The IS makes no such guarantee. Pointers or references to elements are not invalidated, but all iterators may be invalidated.
The elements of an unordered associative container are organized into buckets. Keys with the same hash code appear in the same bucket. The number of buckets is automatically increased as elements are added to an unordered associative container, so that the average number of elements per bucket is kept below a bound.
Rehashing invalidates iterators, changes ordering between elements, and changes which buckets elements appear in, but does not invalidate pointers or references to elements.
...
The insert and emplace members shall not affect the validity of references to container elements, but may invalidate all iterators to the container. The erase members shall invalidate only iterators and references to the erased elements.
...
The insert and emplace members shall not affect the validity of iterators if (N+n) < z * B, where N is the number of elements in the container prior to the insert operation, n is the number of elements inserted, B is the container’s bucket count, and z is the container’s maximum load factor.
> Then i use pointer returned elswhere. Is this safe?
Yes, it is safe. Pointers and references will not change and can be safely used. (As long as the element is not erased, and provided the code that uses the pointer is const-correct.)
> Just seen that my code loads resource even if it is in the set:
You need to first check if the resource is already in the set. find() on the set would be a lot faster than walking through a list.
resource is a class that hold some kind of resource (image, sound...)
resource r(std::forward<TStr>(s));
In resource constructor i pass a string witch holds file name of that resource witch is loaded by some 3d party library function and destroy that in destructor.
A map offers order logN keyed access to elements and also does not invalidate iterators after an erase (except for the one pointing to the erased element)
(internal structure of a map is a tree)
An unordered set (i.e. hash) is likely to invalidate iterators due to the bucket structure described
A list allows erasing elements without invalidating other iterators but access to an arbitrary element will be order N (instead of logN for the map)
My feeling is you are unlikely to notice the difference for this usage anyway
Then the list is a better choice?
I don't need sorting, insertion and deletion is not time critical as far as addresses of elements are not mangled somehow.
Use an unordered_map<>, instead? With a string (file name) as the key and resource as the data. Something like this:
1 2 3 4 5 6 7 8 9 10 11
std::unordered_map< std::string, resource > resource_cache ;
const resource* load_res( const std::string& file_name )
{
auto iter = resource_cache.find( file_name ) ;
if( iter != resource_cache.end() ) return &iter->second ; // found in cache
resource_cache[file_name] = resource(file_name) ; // not found, add to cache
return load_res(file_name) ; // call recursively, will find it next time
}
EDIT: Invalidation of iterators is a non-issue here - no iterators are being passed anywhere. And the pointer that is returned is guaranteed to be valid.