map STL Question
I am wondering what happens when you try to insert the same
key twice in the map STL container.
std::map mymap;
mymap.instert("this",0);
mymap.instert("this",0);
Does it throw an exception, will it return 0 (or something like 0xCCCC6 in VC++''s case), or both? map looks like it will fit the scheme I want to use, but in order to plan properly for it, I must deal with the errors.
Sorry, I left my STL book at home, or I''d look it up myself.
A month ago, I would never beleive that I cared what map did since I would just use C. This C++ is novel.
August 17, 2000 09:17 AM
insert returns a pair< map::iterator, bool > indicating success or failure. No exception is thrown, but it should return false.
e.g.
typedef map< key, data > sample_map;pair< sample_map::iterator, bool > return_value = sample_map.insert( key_item, data_item );if ( return_value.second == false ) //: insert failedelse //: insert succeeded
Course, I am away from my own STL documentation at the moment , but I believe this is correct or at least close enough to lead you in the right direction.
Cool, thanks!
Error handling is a must, so that is good news. All I have to do now is lookup what an invalid key would return when referenced ala:
Error handling is a must, so that is good news. All I have to do now is lookup what an invalid key would return when referenced ala:
std::map mymap;mymap.insert("this",0);mymap.insert("that",0);int x = mymap["theother"];
Carefully read up on that map documentation, because your insert code is wrong. First, if sample_map is your type, you need an object of type sample_map. Also, instead of what you've listed, it should be:
sample_map my_map;
pair<sample_map::iterator, bool> return_value = my_map.insert(sample_map::value_type (key_item, data_item));
Edited by - Stoffel on August 17, 2000 11:53:23 AM
sample_map my_map;
pair<sample_map::iterator, bool> return_value = my_map.insert(sample_map::value_type (key_item, data_item));
Edited by - Stoffel on August 17, 2000 11:53:23 AM
Hmmm...
Without error checking:
I am wondering if insert is overloaded so that it doesn''t need apair definition to insert with and if it could just use raw values.
The first value in the error checking pair, in this case, would be a string , and the second would be a bool ?
Without error checking:
map<string,int> mymap;pair<string,int> Enumerator(string("this"),1);mymap.insert(Enumerator);int x = mymap["this"]; // x = 1
I am wondering if insert is overloaded so that it doesn''t need apair definition to insert with and if it could just use raw values.
The first value in the error checking pair, in this case, would be a string , and the second would be a bool ?
No, there are two pairs here. That''s what''s causing the confusion.
The first pair is defined in map as map::value_type. Your definition of a map template is map<class Key, classT> (ignoring the allocator). The map class gives you a public typdef of value_type, which is typedef pair<const Key, T>. This is what insert needs as its argument. There''s no overload.
The second pair we''re talking about is the pair of values returned from insert. It needs to return both the iterator pointing to the new device, as well as the bool whether the insertion was a success or failure.
Here''s the best example code I can think of (with error-checking):
The first pair is defined in map as map::value_type. Your definition of a map template is map<class Key, classT> (ignoring the allocator). The map class gives you a public typdef of value_type, which is typedef pair<const Key, T>. This is what insert needs as its argument. There''s no overload.
The second pair we''re talking about is the pair of values returned from insert. It needs to return both the iterator pointing to the new device, as well as the bool whether the insertion was a success or failure.
Here''s the best example code I can think of (with error-checking):
typedef map<string, int> SIMap; // gives you SIMap::value_typetypedef pair<SIMap::iterator, bool> SIMapRetVal; // return of insertSIMap my_map;//...// normally I do this all in one line, but I''ll spread it out// so it''s easier to understand:// value_type: you must assign in constructor, because the key is constSIMap::value_type map_record ("this", 1);// return value: the pair returned from the insertionSIMapRetVal ret_val;// finally, do the insertret_val = my_map.insert (map_record);// now you can look at ret_val.second to see if it was successful
To make adding things to a map easier, you can use the make_pair function. It''s a template function which returns std::pair holding both elements. e.g.
Also you should be careful using [] on a map. As well as using it for lookups it is also used for adding elements. So if they key you want to access doesn''t exist, it''ll get inserted into the map with a default constructed value type. [] will return a reference to this value so you can assign to it.
If you want to access an element that might not be in the map, use map::find. It''ll return a iterator to the element found (the iterator will have a first and second member just like std::pair), or to map::end() if it''s not found. Using find and insert is also faster than [], because [] always creates a key and value even if the element already exists (at least it does on my version of STL, I''m not sure if they all do).
typedef std::map<int, int> intMap;intMap my_map;my_map.insert(std::make_pair(1, 3));
Also you should be careful using [] on a map. As well as using it for lookups it is also used for adding elements. So if they key you want to access doesn''t exist, it''ll get inserted into the map with a default constructed value type. [] will return a reference to this value so you can assign to it.
If you want to access an element that might not be in the map, use map::find. It''ll return a iterator to the element found (the iterator will have a first and second member just like std::pair), or to map::end() if it''s not found. Using find and insert is also faster than [], because [] always creates a key and value even if the element already exists (at least it does on my version of STL, I''m not sure if they all do).
Using make_pair doesn''t buy you anything. Just use the standard pair constructor. Compare the difference:
my_map.insert (MapType::value_type (key, value));
..or..
my_map.insert (make_pair (key, value));
I''m not sure, but isn''t it possible that make_pair would create an incompatible type, especially if your key was an unsigned char and you tried to do a make_pair (5, "something)? Wouldn''t that make an int/char* pair?
my_map.insert (MapType::value_type (key, value));
..or..
my_map.insert (make_pair (key, value));
I''m not sure, but isn''t it possible that make_pair would create an incompatible type, especially if your key was an unsigned char and you tried to do a make_pair (5, "something)? Wouldn''t that make an int/char* pair?
quote:
if your key was an unsigned char and you tried to do a make_pair (5, "something)? Wouldn''t that make an int/char* pair?
Yea it would I''ve had that probably a few times with a map that holds pointers then using make_pair with 0. I should probably stop using make_pair for maps and switch to map::value_type. So forget what I said about make_pair It''s not a good idea for maps (but it''s still useful for functions that std::pair).
I remembered to bring the most excellent The C++ Standard Library: A Tutorial and Reference by Nicolai M. Josuttis who points out that it is nice to use the [] to access the map it however does what has been stated - adds a new key if the old one doesn''t exists and gives it a value of 0. map.find(specifier) looks like the most secure way to go. He also says that using [] is slower. map.find(specifier) returns map.end() if no value is found that matches.
Thanks for the pointers!
Thanks for the pointers!
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement
Recommended Tutorials
Advertisement