is there a container for this or write my own?

Started by
13 comments, last by alvaro 12 years, 3 months ago
brainfart... I've got a vector of structs, that contain a string value. I'd like to be able to look into the vector using the string value as the index like so.

vector<struct> myStructs;
int health = myStructs["health"].value;

is there a container that can already do this for me, or should I just wrap the vector in a class that overrides the [] operator? The other things is, it kinda needs some sort of error checking, there's definitely times were the string won't exist, so returning a blank struct (ie 0) would be prefered.
[ dev journal ]
[ current projects' videos ]
[ Zolo Project ]
I'm not mean, I just like to get to the point.
Advertisement
Yes you are looking for http://www.cplusplus.com/reference/stl/map/
Edge cases will show your design flaws in your code!
Visit my site
Visit my FaceBook
Visit my github

Yes you are looking for http://www.cplusplus...erence/stl/map/


ooh, quick question, what happens if I try to push an element onto a map with a key that matchs an already existing element? Do I need to handle these errors on my own or will it ignore the new value?

and what happens if I try to access an element but the key doesn't exist... ie there is no value in the map that has the key "health" but I try to access it anyways?
[ dev journal ]
[ current projects' videos ]
[ Zolo Project ]
I'm not mean, I just like to get to the point.
Both of those questions are thoroughly described in the reference that was linked. Basically, you go to the function you're using to do that and check what the result are and what they mean.

Yo dawg, don't even trip.

The value is overriden. If you want to have more than one element with the same key (the key in this case would be "health") then you're looking into multi_map

Note however, games are performance critical and using strings to address data is very inefficient. And map causes lots of cache misses too. I only use strings (& std::map) to store game's data (i.e. to store it in HDD) and then be processed at loading time. If this is used every frame by every entity in your scene, it may affect your performance seriously.

The value is overriden. If you want to have more than one element with the same key (the key in this case would be "health") then you're looking into multi_map


Are you sure? The reference says it doesn't get modified.

Yo dawg, don't even trip.


Both of those questions are thoroughly described in the reference that was linked. Basically, you go to the function you're using to do that and check what the result are and what they mean.


ok it states that if I try to access a key that doesn't exist it creates a new element with that key.... but does map not use push to add elements? do I have to use insert or the [] operator?


The value is overriden. If you want to have more than one element with the same key (the key in this case would be "health") then you're looking into multi_map

Note however, games are performance critical and using strings to address data is very inefficient. And map causes lots of cache misses too. I only use strings (& std::map) to store game's data (i.e. to store it in HDD) and then be processed at loading time. If this is used every frame by every entity in your scene, it may affect your performance seriously.


nothing huge going on here, I wouldn't think I'd have an issue, if each map i no more than 10-15 elements in size and typically only ~5. and access every map anywhere from 150-3K times every second... I wouldn't think I'd notice it at all. The need for the dynamic storage of data based on a name is more important then an extra fps.

Also I don't need to store multiple values with the same name, in fact that should never happen, but there is the chance that I might try to add another value with the same name, I want the enw value to be completely ignored/rejected, not override the old value.
[ dev journal ]
[ current projects' videos ]
[ Zolo Project ]
I'm not mean, I just like to get to the point.
I'm not sure if that's true, but I think map sorts the objects by key so it can find them quicker.

Yo dawg, don't even trip.


ok it states that if I try to access a key that doesn't exist it creates a new element with that key.... but does map not use push to add elements? do I have to use insert or the [] operator?

If you use /"]operator [] to insert elements, then the new item will overwrite the existing item.

If you instead use the insert() function, it will not replace existing elements, and will return a boolean to indicate success.

You can also use the find() function, to check for an existing item, and then pass the resulting iterator into insert(), which will cut down the cost of performing find+insert.

Tristam MacDonald. Ex-BigTech Software Engineer. Future farmer. [https://trist.am]


ok it states that if I try to access a key that doesn't exist it creates a new element with that key.... but does map not use push to add elements? do I have to use insert or the [] operator?

These have been said by swiftcoder, but just to clarify:

  1. Map doesn't have push_back
  2. myMap["myKey"] = 20 -> creates the entry "myKey" and set it to 20. If "myKey" already existed, it overwrites it's contents.
  3. int myVal = myMap["myKey"]; ->Watch out when you do that, because if the entry "myKey" didn't exist, you may be reading uninitialized memory (unless the mapped value has a default constructor that sets it's contents to valid values).
  4. std::map<int>::iterator it = myMap.find( "myKey" ) -> Reads the value at "myKey". If it didn't exist, returns myMap.end() instead (doesn't create a new entry).



nothing huge going on here, I wouldn't think I'd have an issue, if each map i no more than 10-15 elements in size and typically only ~5. and access every map anywhere from 150-3K times every second... I wouldn't think I'd notice it at all. The need for the dynamic storage of data based on a name is more important then an extra fps.

150 is not the same as 3k; and is not the same per frame than per second. Be sure you understand timing. If you access the map 3k in your loop iteration, that's 3k * 60 = 180k per second; which can badly hurt performance since the keys are strings. 3k per second though, is fine.

Also take in mind:

  1. Map is designed for amortized-time accessing of a large number of elements. That means map is designed to hold like 1.000's or 10.000's of values in the same map. If they're gonna have like 15, may be you should roll your own using a struct and a std::vector with linear search (see std::find). However, if you really access like 3k per second, then may be you just stick to map; it's quicker to code and you won't notice performance problems
  2. The thing about using strings is that, when used carelesssly can greatly increase the memory size as well as the memory fragmentation, which is the most damaging element to a video game. That's the reason of my warning. Cache misses can also cause surprising slowdowns even of cutting edge CPUs.
  3. It's rather strange to see someone doing myMap["health"] to store or read a simple common value like health; which seemed like wrong usage to me. May be you were just using as an example only.


Also I don't need to store multiple values with the same name, in fact that should never happen, but there is the chance that I might try to add another value with the same name, I want the enw value to be completely ignored/rejected, not override the old value.

If you stick to map; don't use myMap["key"] = 10; but rather myMap.insert() like swiftcoder suggested.

This topic is closed to new replies.

Advertisement