what C++ map mean? - c++

I have the following C++ map example code:
map<string,string> &weight2price
....
weight = ...
price = ...
if(weight2price.find(weight) == weight2price.end())
weight2price[weight] = price;
could anyone tell me what it means by
if(weight2price.find(weight) == weight2price.end())

The STL Map is a standard C++ container. It uses unique keys that can be compared to refer to value data being stored inside the container. It works much like an array but unlike an array, the key can be anything and doesn't need to be an integer.
The syntax for a map is:
std::map < Key, Data, Compare, Alloc>
Key - the type of object that will be used as key
Data - the type of object that will be used as data
Compare - a comparison function for the keys
Alloc - The map's allocator, used for all internal memory management
usage:
map[Key] = Data
For further reading about STL maps look here :
http://en.wikipedia.org/wiki/Map_%28C%2B%2B%29
and here: http://www.sgi.com/tech/stl/Map.html
In the code snippet, you are using the function find() from the map. This function returns an iterator pointing to the element from the map that contains the key you were searching for. If that key is not found, the find function will return the iterator pointing to the end of the map. That is what is being checked in the code snippet you attached to your question and if the find function returned the value of the end iterator, this means that the key is not in the map, so it adds the key and data to the map. An optimization for your code was provided by GMan in his comment.
A very basic explanation for an iterator (although not complete) would be that an iterator is a pointer to a pair< Key,Data>.
Hope this helps!

If the key passed to find() does not exist, find() returns end(). So it's saying "If it wasn't found...".
The code could be written better as:
weight2price.insert(std::make_pair(weight, price));
So look-up isn't done twice. (If the key already exists, insert won't do anything.)

It means that weight was not found. Then if it wasn't found, it adds it.

map in C++ is a like hashmap, where a key (in your case weight) is mapped to a value (price).
Here it checks to see if the particular weight is already mapped in this map, if not the find method will return weight2price.end()
In that case the program enters a key-value pair in the map with the line that you greyed out.

Related

c++ map/set iterator not dereferencable using .find

I've relatively new to using maps, and I'm currently getting the Debug Assertion Failed Expression: map/set iterator not dereferencable
When I hit retry it brings me to this section of code:
auto temp = mOpenMap.find(currentNode);
temp->second = false;
I assume this has to do with the .find(currentNode) returning the end of the map, as it didn't find it, but the concerning part here is that doing my manual debugging I found that the only Node in the map indeed contained the exact parts of the currentNode I had it search for.
My map is this:
std::map<PathNode*, bool> mOpenMap
Optimistically what I would like it to do is search for the row and column to ascertain that it is looking at a node that has already been searched so that I can set the accompanying boolean to false.
What I'm wondering, is how do maps generally search for objects? Or better yet, how can I go about making the map search with a custom search?
You should check std::map::find does find the element before dereference the iterator:
auto temp = mOpenMap.find(currentNode);
if (temp != mOpenMap.end()) // check temp is pointing to underneath element of a map
{
temp->second = false;
}
If all you're doing is tracking the presence of some PathNode or other, you'd be better off using a std::set.
As for a custom search, both std::map and std::set work with a collection of values, ordered by a comparator. That comparator can be specified as the second template type when the map or set is defined. If omitted, that comparator defaults to std::less, which simply compares the objects with the less than operator, operator<. As written, your map mOpenMap is using the value of the pointer to perform this comparison, which is probably not what you want.
I suggest you declare and define PathNode::operator<, and replace mOpenMap with a member of type std::set<PathNode>. This will key off of actual PathNode values, rather than pointers (which will probably never collide under normal circumstances).
Remember that your PathNode::operator< should generate a strict ordering of PathNode objects. This is a requirement of the comparator for std::map and std::set. if you don't follow this rule, it will behave erratically, but it will compile and run, so make sure you pay attention to this detail.
Documentation for std::set
You should check the result as billz said. The most likely reason that the find failed is that your map is keyed on PathNode * meaning that it will only find nodes with an exact pointer match. Searching for a pathnode with the same member values as one in the map will not work.
If you need the map to be on PathNode *, then you will need to also supply a predicate as the third parameter of the map. The predicate will need to be written to compare two PathNode * parameters by their member values.

Confused with the standard associative container set and vector

I am familiar with the standard libraries associative container map and the sequence container map. However I cant seem to understand the purpose of a set. While trying to understand std::set online I came across the following statement
A set is an STL container that stores values and permits easy lookup.
For example, you might have a set of strings:
std::set<std::string> S;
You can add a new element by writing
S.insert("foo";.
A set may not contain more than one element with the same key, so
insert won't add anything if S already contains the string "foo";
instead it just looks up the old element. The return value includes a
status code indicating whether or not the new element got inserted
So from the above text it seems to me like the set container only stores key and is not like a map which stores a key and a value. If this is true why is it an associative container and not a sequence container like a map ?
It is not really an associative container as it only stores values. It has the property of a mathematical set that if you put the same value in more than once you still only get one instance of that. This can be very useful. Suppose you were trying to get a list of all the words in a document; a set would be great as they would occur many times in the text but you would just get one of each word in the set.
You may think about it as an association of a key and a boolean value, telling whether the key is present in the set or not.

I need to learn these piece of code written in c++

I have a big piece code that is analyzing some things related to network.
I need to learn some parts of that code. but I couldn't understand the following part. I don't know such a usage.
unordered_map < string, DomainInfo *>::iterator hostTrafficItr;
As far as I know unordered_map gets a key, map pair and contains it (a container).
Your unordered_map has a key of type string, and value of type DomainInfo*. ::iterator declares hostTrafficItr as an iterator to this map type.
It may be a good idea to read a good C++ reference book. If you need an online reference, you could use this: http://www.cplusplus.com/
This is declaration of (probably standard) unorderd_map (see here http://www.cplusplus.com/reference/unordered_map/unordered_map/) iterator.
unordered_map is key->value structure allowing to access DomainInfo* element using string to identify them.
The iterator is a class allowing you to (as the name says) iterate through collection elements providing you access to collections keys and values.
You can access key connected with current iterator value using:
hostTrafficItr->first //Has type string
and value using
hostTrafficItr->second //Has type DomainInfo*
dereference operator returns pair<string, DomainInfo>.
Iterators are most common initialized by .begin() or .end() of the collection.
HTH

unordered_map C++

I am using unordered map like
unorderedmap.insert(make_pair(5, 6));
How could I get the iterator for the position of the key (value 5)? Do I need to use find() again or could I some how get it from the return value?
Thanks.
Assuming you are using this unordered_map, the iterator is:
unorderedmap.insert(make_pair(5, 6)).first;
First of all unordered_map is not a standard container. But if you are using a unordered_map provided by the compiler which provides an API similar to this then it returns a pair of <iterator,bool>. The iterator part of the pair which can be accesses using .first will give you the location where the element got inserted (if it was inserted succesfully, this can be tested using the bool second).
This is taken from http://www.cplusplus.com/reference/stl/map/insert/
So as stated before, use the pair::first to get the iterator.
The first version returns a pair, with
its member pair::first set to an
iterator pointing to either the newly
inserted element or to the element
that already had its same value in the
map. The pair::second element in the
pair is set to true if a new element
was inserted or false if an element
with the same value existed.
The unordered_map interface is similar to the set interface or the map interface in that the insert method returns a std::pair<iterator,bool>:
the bool is true if the insertion took place, it did not take place if an element with a similar key already existed in the container
the iterator points to the right element: either the already existing one or the newly inserted one depending on the case
Therefore, if you only wish to access the element, you can simply use:
map.insert(std::make_pair(key,value)).first
However do check that you do not need to know if the insert was successful or not, in general one care about it :)

What iterator to return for non-existing map How to signkey?

I want to have a function which searches for a key in a collection of maps and returns an iterator to the found key. But what should be returned in case the key cannot be found? I cannot return map::end since the collection of maps can be empty.
Thanks.
map<string, string>::iterator CConfFile::GetKey(const string &SectionName, const string &KeyName)
{
maps<string, map<string, string> >::const_iterator Section = _Sections.find(SectionName);
if (Section != _Sections.end()) {
map<string, string> &Keys = SectionPtr->second;
map<std::string, string>::const_iterator Key = Keys.find(KeyName);
if (Key != Keys.end())
return Key;
}
cerr << "Key " << KeyName << "not found\n";
return WHAT???;
}
If you return an iterator, then that implies that one can actually iterate over all the values. If thats indeed the case, you would have to return a custom iterator type anyway and you should have no problem to denote a special end iterator.
If the iterator isn't intended to be used as an iterator, it might be better to return a pointer to the found object, and a null pointer in case there isn't any.
You could define your own proxy iterator class, which wraps the map iterator and passes on all operations to it. Then your class can have a special "end" value and you can return that value for not found. Caller then needs a way to get an end proxy iterator, for comparison.
If you want to be really flash, your iterator could know how to "step forward" from the end of one contained map to the beginning of the next one, so that it can be used to iterate over all the maps in the collection. Admittedly not in key order.
Another option is to return a pair of (iterator, bool). Your "deep find" already doesn't return the type that find functions usually return when called with a container (i.e. the iterator type of the container), so you can just go for a total change.
Iterators aren't required to be default-constructible, although they often are. So it's actually a bit tricky to have an "meaningless iterator" and be properly portable. You could try default-constructing your map iterator, though, and if it works in your implementation, use that in the case where the bool is false.
I'm not sure what Boost.Optional does with types which aren't default-constructible, but that might be helpful as a return value.
You could build a special NotAKey-class (see the Null-Object-Pattern), and then have a default map that only contains one object of that class. Whenever no key is found or no map exists, you just return that special iterator.
I think you could also try to write a special iterator to return for such cases yourself, but I never tried that, so I'm not sure.
EDIT: I think sbi's answer is much better than mine, only you should not return a pointer, but a reference, and then use a reference to the Null-Object (could be global singleton) instead of a null-pointer.
Even if this doesn't answer your question I wanted to post in case this can help you.
I find your problem very interesting. We could define of a new generic multi key map class that allows to behave like a map > and in addition as a map, T> allowing to iterate over all the elements on the collection. Boost.Multi-Index allows to define several index over a collection, but I don't think different index can iterate over different types. I will check this and come back with more info.
I don't know what are the other uses of your map of maps, but if you don't need to iterate over the map of keyName you can transform it into a map, string>, and so you will be able to return just map, string>::end.
You should use map::end, since it doesn't point to the last value but it's special value meaning "you've reached end of the list" and doesn't contain any value.
Read http://msdn.microsoft.com/en-US/library/c84shb7e%28v=VS.80%29.aspx
Focus on overview and remarks.